2011-02-10 54 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語句。嚴重的是,這個問題很模糊 – 2011-02-10 19:48:11

+1

請不要使用開關。 – 2011-02-10 19:49:04

回答

0

我想你應該考慮用決策樹來解決這個問題,其中不同的節點是可能的最終狀態。 然後你可以在樹中構建你的問題,並擺脫所有這些ifs ......

0

我採取了類似的方法來您的case語句一次當我需要基於一組條件聚合數據時,其中有五個開關可以打開或關閉。

爲了處理關於可能情況的聚合信息,這個工作正常,但在該用例之外,如果真的有n^2個不同的動作,那麼我會堅持使用多個if語句。如果沒有真正的排列組合,我會將相似的結果組合在一起以減少ifs的數量。

0

是的,還有更好的辦法。

哦,你想要更多的細節嗎?那麼,你似乎有一些有四個變量的真值表。有16個可能的結果(2^4),還是你只對一個子集感興趣?如果有一個變量的結果數量大致相等,那麼可以將其用作最高級if語句,並使用嵌套ifs。

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

我會把你的四個布爾值作爲四位,所以它是一個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 ""; }}; 
}