web-dev-qa-db-fra.com

Remplacer l'instruction if else avec pattern

J'ai une déclaration if else qui pourrait se développer dans un proche avenir. 

    public void decide(String someCondition){

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

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

           //
           someMethod("anotherParameter");

        }
        .
        .
        else{

            someMethod("elseParameter");

        }
}

Comme cela a déjà l'air désordonné, je pense que ce serait mieux si je pouvais appliquer n'importe quel modèle de conception ici. J'ai examiné le modèle de stratégie, mais je ne suis pas sûr que cela réduira la situation, sinon. Aucune suggestion?

29
cosmos

C’est un classique Remplacez le répartiteur de condition par Commande dans le livre Refactoring en Patterns.

enter image description here

En gros, vous créez un objet Command pour chacun des blocs de code de votre ancien groupe if/else, puis vous créez une mappe de ces commandes dans laquelle les clés sont votre condition.

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

Alors, au lieu de votre code if/else, c'est plutôt:

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

Maintenant, si vous avez besoin d’ajouter de nouvelles commandes ultérieurement, il vous suffit d’ajouter au hachage.

Si vous souhaitez gérer un cas par défaut, vous pouvez utiliser le modèle Null Object pour gérer le cas où une condition ne figure pas dans la carte.

 Handler defaultHandler = ...

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

La recommandation générale de Martin Fowler est de Remplacer le conditionnel par un polymorphisme .

En termes de modèles de conception, il s’agirait souvent du modèle de stratégie Remplacer la logique conditionnelle par la stratégie .

Si vous avez un ensemble petit et fini de conditions, je vous recommande d'utiliser un enum pour implémenter le modèle de stratégie (fournissez une méthode abstraite dans l'énum et remplacez-la pour chaque constante). 

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

}

Si vous voulez uniquement choisir un paramètre, vous pouvez définir l'enum comme ceci:

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

}
14
Puce

J'imagine que vous devez déjà l'avoir envisagé, mais si vous utilisez JDK 7 ou version ultérieure, vous pouvez activer les chaînes. De cette façon, votre code peut sembler plus propre qu'un tas de déclarations if-else.

0
mehmetakcay