我正在审查一些代码(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?我只是想过度设计它吗?
关于如何处理这样的逻辑流程的任何建议? 感谢
答案 0 :(得分:3)
这可以这样建模:
Place
的根类calculateDestination(Person)
。地方可以包含其中的其他地方。Place
和Zoo
创建ZooQuadrant
子类(当然,因为这些是实际位置)。Person
对象的值为currentPlace
和currentDirection
现在,您将实例化这些类的对象以表示您的情况:
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)
是多态方法。继承层次结构中的每个级别都将根据该类的特定语义覆盖它。
Place
将有一个通用实现,用于测试Person
实例当前是否在该节点上(通过测试Person
的{{1}}的值)和如果没有,它会在每个孩子身上调用currentPlace
并返回。calculateDestination
需要检查是否Zoo
,如果是,请在每个象限上调用currentPlace == this
并将任何正面结果与其自身结合以返回calculateDestination
this.name + quadrantResult
只需要检查ZooQuadrant
是否等同于自己的方向,并相应地返回一个值。 注意:这只是为了说明多态可能如何工作,可能有更好的实现。此外,这里我们使用多态和递归,两者是独立的。
编辑:
至于是否需要增加复杂性,这取决于!在这里,我们使用一个非常小的对象图的简单示例。一旦你拥有数十个动物园,就必须在这些动物园中添加更多象限,或者需要做出额外的决策(如果每个象限都有子参数),嵌套的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
子类化为Home
,Zoo
等等,也可以提供name
字段来区分不同的Location
。或者你可以将这两者结合起来。
请注意,这是一种半生不熟的设计,可能会或可能不会满足您的需求。良好的OO设计需要经验和详细了解您要解决的问题的确切要求。我有一些前者,但很少了解后者。
答案 7 :(得分:0)
我尝试了一些建议答案的变体。
我最终使用了嵌套的开关盒。不是最理想的,我想避免的,但为了我的目的,它更易于维护(它不会改变或扩展)。
我要将@Ezequiel Muns方法标记为正确,因为我的版本效果非常好 - 它不是问题所需要的。
感谢所有帮助。