2011-02-10 3 views
5

i potentiellement avoir un ensemble de déclarations qui se ressemblent à ceci:simplifier énorme si déclarations - modèle de conception?

if (a and b and c and d) { 
    // do stuff 
} else (!a and b and c and d) { 
    // do something else 
} else (!a and !b and c and D) { 
    // do yet something else 
} ... 

et ainsi de suite pour toutes les permutations possibles.

je pensais faire:

switch ((a ? 'Y' : 'N') . (b ? 'Y' : 'N') . (c ? 'Y' : 'N') . (d ? 'Y' : 'N')) { 

    case 'YNYN': 
    // do stuff 
    break; 

    case 'NNNN': 
    // etc. 
    break; 

} 

est-il une meilleure façon?

+4

Utilisez moins d'instructions if. Sérieusement, cette question est si vague –

+1

Bien ne pas utiliser l'interrupteur, s'il vous plaît. –

+2

Je ne pense pas que 'and 'fonctionnerait ici (à l'intérieur du commutateur). Utilisez '.'? http: // codepad.org/X4fIQsSz – Dogbert

Répondre

0

Je pense que vous devriez envisager de résoudre ce problème avec des arbres de décision, où différents nœuds sont des états finaux possibles. alors vous pouvez composer votre problème dans un arbre, et se débarrasser de tous ces ifs ....

0

J'ai pris une approche similaire à votre déclaration de cas une fois quand j'avais besoin d'agréger des données en fonction d'un ensemble de conditions, dont il y avait cinq interrupteurs qui pouvaient être allumés ou éteints. Pour traiter l'agrégation d'informations sur les situations possibles, cela a bien fonctionné, mais en dehors de ce cas d'utilisation, s'il y a vraiment deux actions différentes, alors je m'en tiendrai aux multiples instructions if. S'il n'y a pas vraiment beaucoup de permutations, je regrouperais les mêmes résultats pour réduire le nombre de si.

0

Oui, il existe un meilleur moyen.

Oh, voulez-vous plus de détails que cela? Eh bien, vous semblez avoir une sorte de table de vérité avec quatre variables. Y a-t-il 16 résultats possibles (2^4), ou êtes-vous uniquement intéressé par un sous-ensemble? S'il y a une variable qui a un nombre à peu près égal de résultats de toute façon, peut-être l'utiliser comme vos instructions if les plus élevées, et utiliser des ifs imbriquées.

if (b) { 
    // cases where b is true 
    if (...) 
    ... 
} else { 
    // cases where b is false 
    if (...) 
    ... 
} 

Vous pouvez également utiliser une instruction switch, mais plutôt qu'une chaîne composée de Y et N utilise des champs de bits.

7

Ce que je ferais probablement (sans connaître les détails) est de construire une série de classes pour chaque état. Puis pousser le doStuff sur cette classe:

class DoStuff { //The Client 
    protected $strategies = array(); 
    public function addStrategy(iDoStuffStrategy $strategy) { 
     $this->strategies[] = $strategy; 
    } 
    public function doStuff ($a, $b, $c, $d) { 
     foreach ($this->strategies as $strategy) { 
      if ($strategy->test($a, $b, $c, $d)) { 
       return $strategy->doStuff(); 
      } 
     } 
     throw new RuntimeException('Unhandleable Situation!'); 
    } 
} 

interface iDoStuffStrategy { 
    // Return a bool if you can handle this situation 
    public function test($a, $b, $c, $d); 
    // Execute the implementation 
    public function doStuff(); 
} 

Ensuite, chaque classe ressemblerait à ceci:

public function StrategyFoo implements iDoStuffStrategy { 
    public function test($a, $b, $c, $d) { 
     return $a && $b && $c && $d; 
    } 
    public function doStuff() { 
     //DoStuff! 
    } 
} 
public function StrategyBar implements iDoStuffStrategy { 
    public function test($a, $b, $c, $d) { 
     return !$a && $b && $c && $d; 
    } 
    public function doStuff() { 
     //DoStuff! 
    } 
} 

Il est essentiellement une mise en œuvre du Strategy Pattern. Le faire de cette façon vous permet de séparer l'arbre de décision.

+0

+1 Cette approche ou quelque chose de similaire est ce qu'il faut. Chaque fois que vous avez un long jeu d'instructions switch, il est probablement préférable d'utiliser plus de style de POO. – NotMe

+0

@ircmaxwell ... J'essaie d'utiliser une version de ce code et je suis curieux de savoir s'il me manque quelque chose. Comment la méthode 'addStrategy' ajoute-t-elle les objets à la variable' $ strategy'? J'adore ce modèle de design et je voudrais l'implémenter, mais je ne peux pas le faire fonctionner. – tollmanz

0

Je traiterais vos quatre booléens comme quatre bits, donc comme un entier entre 0 et 15. Je créerais un tableau avec 16 éléments, et stocker un pointeur de fonction dans chaque élément du tableau. Chaque fois que vous devez le faire, j'évalue les booléens dans un modèle binaire, convertit en int, et appelle la méthode stockée dans cet index du tableau.

Je sais que vous posez des questions sur PHP, dont j'ai peur je ne sais pas. En C#, vous pouvez faire quelque chose comme ceci:

static class Multiplexer 
{ 
    public static string Multiplex(bool a, bool b, bool c, bool d) 
    { 
     var i = 0; 
     i |= (a ? 1 : 0) << 3; 
     i |= (b ? 1 : 0) << 2; 
     i |= (c ? 1 : 0) << 1; 
     i |= (d ? 1 : 0); 
     return _functions[i](); 
    } 

    private static Func<string>[] _functions = new Func<string>[] { 
     () => { return "pie";}, 
     () => { return "index 1"; }, 
     () => { return DateTime.Now.ToString(); }, 
     () => { return "pie";}, 
     () => { return "index 1"; }, 
     () => { return DateTime.Now.ToString(); }, 
     () => { return Assembly.GetExecutingAssembly().FullName; }, 
     () => { return ""; }, 
     () => { return "pie";}, 
     () => { return "index 1"; }, 
     () => { return DateTime.Now.ToString(); }, 
     () => { return "pie";}, 
     () => { return "index 1"; }, 
     () => { return DateTime.Now.ToString(); }, 
     () => { return Assembly.GetExecutingAssembly().FullName; }, 
     () => { return ""; }}; 
}