活用設計模式:如何避免一連串的if else

另載於 http://www.qingjingjie.com/blogs/8程序員

前段時間知乎上有人發了這麼個段子:算法

某日,老師在課堂上想考考學生們的智商,就問一個男孩: 「樹上有十隻鳥,開槍打死一隻,還剩幾隻?」 
男孩反問:「是無聲手槍,仍是其餘沒有聲音的槍麼?」 
「不是.」 
「槍聲有多大?」 
「80~100分貝.」 
「那就是說會震的耳朵疼?」 
「是.」 
「在這個城市裏打鳥犯不犯法?」 
‘不犯.」 
「您肯定那隻鳥真的被打死啦?」 
「肯定.」老師已經不耐煩了,」拜託,你告訴我還剩幾隻就好了,OK?」 
「OK.鳥裏有沒有聾子?」 
「沒有.」 
「有沒有鳥智力有問題,呆傻到聽到槍響不知道飛的?」 
「沒有,智商都在200以上!」 
「有沒有關在籠子裏的?」 
「沒有.」 
「邊上還有沒有其餘的樹,樹上還有沒有其餘鳥?」 
「沒有.」 「方圓十里呢?」 「就這麼一棵樹!」 
「有沒有殘疾或餓的飛不動的鳥?」 
「沒有,都身體倍棒.」 
「算不算懷孕肚子裏的小鳥?」 
「都是公的.」 
「都不可能懷孕?」 
「………,決不可能.」 
「打鳥的人眼裏有沒有花?保證是十隻?」 
「沒有花,就十隻.」 老師腦門上的汗已經流下來了, 
下課鈴響起,但男孩仍繼續問:「有沒有傻的不怕死的?」 
「都怕死.」 
「有沒有由於情侶被打中,本身留下來的?」 
「笨蛋,以前不是說都是公的嘛!」 
「**可不能夠啊!」 
「………….,性取向都很正常!」 
「會不會一槍打死兩隻?」 
「不會.」 
「一槍打死三隻呢?」 
「不會.」 
「四隻呢?」 
「更不會!」 
「五隻呢?」 
「絕對不會!!!」 
「那六隻總有可能吧?」 
「除非你他媽的是豬生的纔有可能!一槍只能打死一隻!」 
「…好吧,那麼全部的鳥均可以自由活動麼?」 
「徹底能夠.」 
「它們受到驚嚇起飛時會不會惶恐不安而互相撞上?」 
「不會,每隻鳥都裝有衛星導航系統,並且能夠自動飛行.」 
「恩,若是您的回答沒有騙人,」學生滿懷信心的回答,「打死的鳥要是掛在樹上沒掉下來,那麼就剩一隻,若是掉下來,就一隻不剩.」 
老師推推眼鏡,強忍着要昏倒的感受,顫抖地說道:「你能夠去當程序員了……」

有人就在下面問怎麼寫代碼才能避免一連串的if else?設計模式

由於他用Python,我就回答:把每個條件判斷都寫成一個布爾函數,把這些函數依次放進一個數組/列表。再寫一個函數來遍歷數組,對每一項,若爲假則返回,若爲真則繼續。數組

對Java(8以前)來講,沒有一等函數,就要把每一個條件判斷寫成Function接口的實現類。app

而用Java 8來寫,就是:函數

Collection<Function<Context, Boolean>> conditions = new ArrayList<>();
conditions.add(context -> isGunSilent(context));
conditions.add(context -> isGunSoundBig(context));
conditions.add(context -> isShootingBirdLegal(context));
...

public boolean judge(Context context, Collection<Function<Context, Boolean>> conditions) {
    for (Function<Context, Boolean> cond : conditions) {
        if (!cond.apply(context)) {
            return false;
        }
    }
    return true;
}

Context是個包裝類,包含了gun, city, bird, tree等數據。設計

折騰以後,代碼量相比一連串if else略有減小,彷佛收益不大?噢,值得注意的是,這種方法具備高度的靈活性!code

這些條件能夠提早定義好,而後處處複用!你能夠任意地組合它們,來構造一段業務邏輯,只須要挑選你要的條件,塞到一個list裏面!簡直棒!blog

這是用了哪一種設計模式呢,比較像Strategy,我認爲還像Template Method: 定義一個操做中的算法的骨架,而將一些步驟延遲到子類中。
咱們定義了做爲骨架的judge():for循環,遇到false停止。而後在把步驟在子類中實現(雖然與judge()不屬於同一個父類)。
雖然結構跟書上不同,可是有相同的精神。接口

Chain of Responsibility須要先後連接,節點對其後的子鏈有控制力,因此不那麼像。

相關文章
相關標籤/搜索