避免嵌套如果Else / Switches - Java

时间:2013-01-10 00:53:18

标签: java polymorphism if-statement

我正在审查一些代码(Java)并根据业务逻辑流程图进行更改。当前的代码依赖于大量的if语句 - 我想尝试并远离它。我一直在阅读有关多态性的文章,并试图围绕如何将其应用于我的情况。我可以使它适用于单个级别的条件,但努力在多个条件级别进一步扩展它。代码将在运行时执行,这个'Logic'方法将传递上一步的变量。

Contrived Example: 我们有2个动物园,'动物园A'和'动物园B','家'。每个都是'地方'。在每个动物园,我们有4个'位置','北','南','东'和'西'。 'Home'只有一个位置。 我们希望根据一些变量为一个人分配一个“目的地”。 这些变量是:     '地方',与我们的地方相关(动物园A,动物园B,家庭)。     '方向',与我们的位置相关,(N,S,E,W)。 流程图:

                |----- | 'HOME'
                |Place?| ----- >  *destination = 'home'*
                |----- |
     Zoo A          |                               Zoo B
    |---------------|----------------------------------------|
|----------|                                        |----------| 
|Direction?|                                        |Direction?| 
|----------|                                        |----------|
    |    North                                          |    North
    ----------- *destination = 'Zoo A North'            ----------- *destination = 'Zoo B North'
    |    East                                           |    East
    ----------- *destination = 'Zoo A East'             ----------- *destination = 'Zoo B East'
    |    South                                          |    South
    ----------- *destination = 'Zoo A South'            ----------- *destination = 'Zoo B South'
    |    West                                           |    West
    ----------- *destination = 'Zoo A West'             ----------- *destination = 'Zoo B West'

因此,如果人物X有一个动物园A和一个南方的位置,他们应该有一个'动物园南方'的目的地

我的代码目前使用If语句非常难看:

if(Place = 'HOME')
    destination = 'HOME'
if(Place = 'Zoo A')
    if(Direction = North)
        destination = 'Zoo A North')
    if(Direct = East)
        destination = 'Zoo A East')
    ...
if(Place = 'Zoo B')
    if(Direction = North)
        destination = 'Zoo B North')
    if(Direct = East)
        destination = 'Zoo B East')
    ...

我可以将此变为嵌套开关,变量为ENUM。但我试图避免if - else / switch依赖,因为我有一个不好的习惯。我尝试使用Factory Design来生成Place类,然后在每个位置和目标上使用Polymorphism,但它开始变得过于复杂。是否值得远离if / switches?我只是想过度设计它吗?

关于如何处理这样的逻辑流程的任何建议? 感谢

8 个答案:

答案 0 :(得分:3)

这可以这样建模:

  1. 使用方法Place的根类calculateDestination(Person)。地方可以包含其中的其他地方。
  2. PlaceZoo创建ZooQuadrant子类(当然,因为这些是实际位置)。
  3. Person对象的值为currentPlacecurrentDirection
  4. 现在,您将实例化这些类的对象以表示您的情况:

    zooA = new Zoo("ZooA");
    zooA.addChild(new ZooQuadrant(Direction.SOUTH));
    ... so on for every quadrant ...
    ... same for zooB ...
    home = new Place("Home");
    world = new Place("World");
    world.addChild(home);
    world.addChild(zooA);
    world.addChild(zooB);
    

    如果您想获得目的地,请致电world.calculateDestination(myPerson)

    calculateDestination(Person)是多态方法。继承层次结构中的每个级别都将根据该类的特定语义覆盖它。

    1. Place将有一个通用实现,用于测试Person实例当前是否在该节点上(通过测试Person的{​​{1}}的值)和如果没有,它会在每个孩子身上调用currentPlace并返回。
    2. calculateDestination需要检查是否Zoo,如果是,请在每个象限上调用currentPlace == this并将任何正面结果与其自身结合以返回calculateDestination
    3. 每个this.name + quadrantResult只需要检查ZooQuadrant是否等同于自己的方向,并相应地返回一个值。
    4. 注意:这只是为了说明多态可能如何工作,可能有更好的实现。此外,这里我们使用多态和递归,两者是独立的。


      编辑:

      至于是否需要增加复杂性,这取决于!在这里,我们使用一个非常小的对象图的简单示例。一旦你拥有数十个动物园,就必须在这些动物园中添加更多象限,或者需要做出额外的决策(如果每个象限都有子参数),嵌套的if-else-if方法(程序)真的得到了毛茸茸的很快,而面向对象的方法仍然可以维护和理解。

      就像所有事情一样,如果您预见到决策会变得那么复杂,那么请使用OO方法。否则,保持简单就是每次都胜过美丽:使用正确的工具来解决正确的问题。

答案 1 :(得分:0)

一种方法是你可以使用方法getNorthDestination(),getEastDestination()等创建父asbtract类/接口'Place'。

然后创建一个名为'ZooA'和'ZooB'的'Place'的子类/实现,并覆盖/实现getXXXDestination()方法以返回相应的位置

答案 2 :(得分:0)

从这里我看到你想要的至少三个课程是Place,Direction和Destination。

Place将具有name属性和getName()方法,其名称设置为Zoo A,Zoo B,Home。

如果Place具有不同的行为,您可以创建Place的Home和Zoo子类。 在这种情况下,你可以这样做,因为Home没有方向,但Zoo也没有。

方向可以是包含北,东,西,南的枚举(只是一种特殊类型)。

目的地将有两个属性,即Place和Direction。它还有一个方法getDestination()

public String getDestination(){
    if (this.direction == null){
        result = this.place.getName();
    } else {
        result = this.place.getName() + " " + this.direction.getName();
    }
    return result;
}

答案 3 :(得分:0)

跟Gerrytan一起回答。对于每一条信息,你应该问自己,“我真的需要一个课程吗?”。很多时候,答案是否定的。简单的字符串/数值变量就足够了。现在,您希望将这些变量与getter / setter方法结合起来,因为这是java强调的,而不是直接引用公共变量(例如C ++)。例如,引用简单方法比测试容易得多。

答案 4 :(得分:0)

你可以使用Zoo A和Zoo B创建一个新方法...... 你可以像directionForZoo()一样调用它,如果尝试使用while循环

答案 5 :(得分:0)

如果您不想过度设计它,以下解决方法将是摆脱if / else的简单解决方案。但这不是一种优雅的方法。

您可以拥有一个地图,其中的键是(Place + Direction),值是相应的目的地。只有当你的程序中的Place和Direction值更像是静态并且它不太可能发生太大变化时,这是很好的。

例如:将地点和相应的目的地存储在地图中

Map<String, String> destMap = new HashMap<String, String>();
destMap.put("HOME","HOME");
destMap.put("Zoo A+North","Zoo A North");
destMap.put("Zoo A+East","Zoo A East");
destMap.put("Zoo B+North","Zoo B North");

根据地点和方向检索目的地:

destMap.get(Place + "+" + Direction);

答案 6 :(得分:0)

您的示例的一个可能解决方案是创建一个(可能是抽象的)Location类。这可以包含目的地的数据结构。这种数据结构的一种可能性可能是Map<Direction, Location>)其中Direction是一个枚举,它可以用作映射到Location对象的键,该对象是朝着那个方向前进的目的地。您可以将Location子类化为HomeZoo等等,也可以提供name字段来区分不同的Location。或者你可以将这两者结合起来。

请注意,这是一种半生不熟的设计,可能会或可能不会满足您的需求。良好的OO设计需要经验和详细了解您要解决的问题的确切要求。我有一些前者,但很少了解后者。

答案 7 :(得分:0)

我尝试了一些建议答案的变体。

我最终使用了嵌套的开关盒。不是最理想的,我想避免的,但为了我的目的,它更易于维护(它不会改变或扩展)。

我要将@Ezequiel Muns方法标记为正确,因为我的版本效果非常好 - 它不是问题所需要的。

感谢所有帮助。