2011-02-10 6 views
5

私は潜在的のセットを持って次のようになりif文:すべての可能な組み合わせのための巨大なif文を簡略化する - デザインパターン?

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

のように。

私はこれをやって考える:

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

    case 'YNYN': 
    // do stuff 
    break; 

    case 'NNNN': 
    // etc. 
    break; 

} 

は、より良い方法はありますか?

+4

if文が少なくて済みます。真剣に、この質問はあまりにも曖昧です –

+1

よくスイッチを使用しないでください。 –

+2

ここでは 'と'は(スイッチの内部で)動作するとは思わない。 '.'を使う? http://コードパッド。org/X4fIQsSz – Dogbert

答えて

0

私はあなたが異なるノードが可能な終了状態である決定木でこの問題を解決することを検討するべきだと思います。 あなたはツリーで問題を作成し、これらのifsを取り除くことができます....

0

条件の集合に基づいてデータを集計する必要があるときに、そのうち5つのスイッチがオンまたはオフになる可能性があります。

これはうまくいきましたが、そのユースケースの外で、実際にn^2の異なるアクションがある場合は、複数のif文に固執します。本当に多くの順列がない場合は、ifの数を減らすために同様の結果をまとめます。

0

はい、良い方法があります。

ああ、それ以上の詳細は知りましたか?まあ、あなたは4つの変数で何らかの真理値表を持っているようです。 16の結果(2^4)がありますか、またはサブセットのみに興味がありますか?いずれかの方法で結果の数がおおよそ等しい変数が1つある場合は、おそらくこれを最上位のif文として使用し、ネストされたifを使用します。

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

また、switch文を使用できますが、YとNで構成される文字列ではなく、ビットフィールドを使用します。

7

私が(具体的なことを知らないうちに)できることは、各状態の一連のクラスを構築することです。そして、そのクラスにdoStuffを押す:

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

その後、各クラスには、次のようになります。

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! 
    } 
} 

それは基本的にStrategy Patternの実装です。そのようにすれば、意思決定ツリーを分けることができます。

+0

+1このようなやり方が似ています。 switch文のセットが長いときはいつでも、より多くのOOPスタイルの考え方を使うのが最善でしょう。 – NotMe

+0

@ircmaxwell ...私はこのコードのバージョンを使用しようとしていると私は何かが不足している場合は好奇心が強いです。 'addStrategy'メソッドはオブジェクトを' $ strategy'変数にどのように追加しますか?私はこのデザインパターンが大好きで、それを実装したいと思っていますが、私はその部分を機能させることができません。 – tollmanz

0

私は4つのブール値を0と15の間の整数で扱います。私は16の要素で配列を作成し、配列の各要素に関数ポインタを格納します。あなたがこれを行う必要があるたびに、私はブール値をビットパターンに評価し、intに変換し、その配列のインデックスに格納されたメソッドを呼び出します。

PHPについて質問していることはわかっていますが、わかりません。 C#では、次のようなことができます。

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