web-dev-qa-db-ja.com

if elseステートメントをパターンに置き換える

近い将来に成長するかもしれないif elseステートメントがあります。

    public void decide(String someCondition){

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

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

           //
           someMethod("anotherParameter");

        }
        .
        .
        else{

            someMethod("elseParameter");

        }
}

これはすでに厄介に見えるので、ここでデザインパターンを適用できると良いと思います。私は戦略パターンを調べましたが、それが他の条件をここで減らすかどうかはわかりません。助言がありますか?

36
cosmos

これは古典的な 「パターンのリファクタリング」ブックのコマンド で条件ディスパッチャを置き換えます。

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);

後で新しいコマンドを追加する必要がある場合は、ハッシュに追加するだけです。

デフォルトのケースを処理する場合は、Null Object条件がマップにない場合を処理するパターン。

 Handler defaultHandler = ...

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

Martin Fowlerによる一般的な推奨事項は、 Conditional with Polymorphism です。

設計パターンの観点では、これはしばしば戦略パターンになります 条件付きロジックを戦略に置き換える

条件の小さな有限セットがある場合は、enumを使用して戦略パターンを実装することをお勧めします(要約を提供します)列挙型のメソッドを使用し、定数ごとにオーバーライドします)。

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 SomeCondition(String parameter){
       this.parameter = parameter;
   }

   public String getParameter(){
       return parameter;
   }

}


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

}
17
Puce

すでに検討しているに違いありませんが、JDK 7以降を使用している場合は、文字列を有効にできます。そうすれば、コードはif-elseステートメントの束よりもきれいに見えます。

0
mehmetakcay