将 if else 语句替换为模式

2022-08-31 12:30:25

我有一个如果还有声明,可能会在不久的将来增长。

    public void decide(String someCondition){

        if(someCondition.equals("conditionOne")){
            //
            someMethod("someParameter");

        }else if(someCondition.equals("conditionTwo")){

           //
           someMethod("anotherParameter");

        }
        .
        .
        else{

            someMethod("elseParameter");

        }
}

由于这已经看起来很混乱,我认为如果我能在这里应用任何设计模式会更好。我研究了策略模式,但我不确定如果这里还有其他条件,这是否会减少。有什么建议吗?


答案 1

这是一个经典的“将条件分派器替换为模式重构”一书中的命令。

enter image description here

基本上,您为旧的if/else组中的每个代码块创建一个对象,然后制作一个映射,其中键是您的条件字符串Command

interface Handler{
    void handle( myObject o);
}


 Map<String, Handler> commandMap = new HashMap<>();
 //feel free to factor these out to their own class or
 //if using Java 8 use the new Lambda syntax
 commandMap.put("conditionOne", new Handler(){
         void handle(MyObject o){
                //get desired parameters from MyObject and do stuff
          }
 });
 ...

然后,它不是你的if/else代码,而是:

 commandMap.get(someCondition).handle(this);

现在,如果以后需要添加新命令,只需添加到哈希值即可。

如果要处理默认情况,可以使用模式来处理条件不在 Map 中的情况。Null Object

 Handler defaultHandler = ...

if(commandMap.containsKey(someCondition)){
    commandMap.get(someCondition).handle(this);
}else{
    defaultHandler.handle(this);
}

答案 2

Martin Fowler的一般建议是用多态性替换条件。

就设计模式而言,这通常是策略模式用策略替换条件逻辑

如果你有一个小的、有限的条件集,我建议使用枚举来实现策略模式(在枚举中提供一个抽象方法,并为每个常量重写它)。

public enum SomeCondition{
   CONDITION_ONE{

       public void someMethod(MyClass myClass){
              //...
       }
   },

   CONDITION_TWO{

       public void someMethod(MyClass myClass){
       }

   }

   public abstract void someMethod(MyClass myClass);

}

public class MyClass{
//...
    public void decide(SomeCondition someCondition){
        someCondition.someMethod(this);
    }

}

如果它真的只是一个你想要选择的参数,那么你可以像这样定义枚举:

public enum SomeCondition{
   CONDITION_ONE("parameterOne"),

   CONDITION_TWO("parameterTwo");

   private final String parameter;

   private SomeCondition(String parameter){
       this.parameter = parameter;
   }

   public String getParameter(){
       return parameter;
   }

}


public class MyClass{
//...
    public void decide(SomeCondition someCondition){
        someMethod(someCondition.getParameter());
    }

}