解鎖新姿勢:探討複雜的 if-else 語句“優雅處理”的思路

juejin.im/post/5def654f51882512302daeef

前言

在之前文章說到,簡單 if-else,可以使用 衛語句 進行優化。但是在實際開發中,往往不是簡單 if-else 結構,我們通常會不經意間寫下如下代碼:


毫不誇張的說,我們都寫過類似的代碼,回想起被 if-else 支配的恐懼,我們常常無所下手,甚至不了了之。

下面分享一下我在開發中遇到複雜的 if-else 語句“優雅處理”思路。如有不妥,歡迎大家一起交流學習。

需求

假設有這麼一個需求:

一個電商系統,當用戶消費滿1000 金額,可以根據用戶VIP等級,享受打折優惠。
根據用戶VIP等級,計算出用戶最終的費用。

普通會員 不打折白銀會員 優惠50元黃金會員 8折白金會員 優惠50元,再打7折

編碼實現

為了方便演示,代碼上我進行了簡單實現,但實際上 if - else 會進行復雜的邏輯計費。從功能上來說,基本完成,但是對於我這種有代碼潔癖的人來說,代碼質量上不忍直視。我們開始著手 優化一下我們的第一版代碼吧。

思考

看到如上代碼,聰明的朋友首先想到的是,這不是典型的策略模式嗎?

你可真是個機靈鬼,我們先嚐試用策略模式來優化一下代碼吧。

策略模式

什麼是策略模式?

可能有的朋友還不清楚,什麼是策略模式。策略模式是定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。

比如上述需求,有返利、有打折、有折上折等等。這些算法本身就是一種策略。並且這些算法可以相互替換的,比如今天我想讓 白銀會員優惠50,明天可以替換為 白銀會員打9折。

說了那麼多,不如編碼來得實在。

編碼


我們定義來一個 Strategy 接口,並且定義 四個子類,實現接口。在對應的 compute方法 實現自身策略的計費邏輯。

然後對應 getResult 方法,根據 type 替換為對應的 用戶VIP 策略。這裡代碼上出現了重複的調用 compute ,我們可以嘗試進一步優化。

還記得我在第一篇中說到的衛語句嗎?我們在這裡把 money < 1000 的情況提前 return。更關注於滿1000邏輯 ,也可以減少不必要的縮進。

深思

我曾一度 以為 策略模式不過如此。以為代碼優化到這已經可以了。

但是還有一個恐怖的事情,if-else 依然存在 :)

我嘗試翻閱了許多書籍,查看如何消除 策略模式中的 if-else

書中大部分的方法是,使用簡單工廠 + 策略模式。把 if - else 切換為 switch 創建一個工廠方法而已。

但是這遠遠沒有達到我想要的效果,打倒 if - else

直到某一天夜裡,我大佬在群裡分享一個 Java8 小技巧時,從此打開新世界。

工廠 + 策略

我們先在 Strategy 新增一個 getType 方法,用來表示 該策略的 type 值。代碼相對簡單,這裡就不過多介紹了

靜態內部類單例,單例模式實現的一種,不是本文重點,如不瞭解,可以自行 google

我們再著手創建一個 StrategyFactory 工廠類。StrategyFactory 這裡我使用的是靜態內部類單例,在構造方法的時候,初始化好 需要的 Strategy,並把 list 轉化為 map。

這裡 轉化就是“靈魂”所在。

toMap

我們先來看看 Java8 語法中的小技巧。
通常情況下,我們遍歷 List,手動put到 Map 中。

toMap 第一個參數是一個Function,對應 Map 中的 key,第二個參數也是一個Function,strategy -> strategy, 左邊strategy 是遍歷 strategies 中的每一個strategy,右邊strategy則是 Map 對應 value 值。

若是不瞭解 Java8 語法的朋友,強烈建議看 《Java8 實戰》,書中詳細的介紹了 Lambda表達式、Stream等語法。

效果

至此,通過一個工廠類,在我們在 getResult()調用的時候,根據傳入 type,即可獲取到 對應 Strategy

再也沒有可怕的 if-else 語句。

完結撒花撒花 : )

後續

後續代碼優化上,若是 Java 項目,可以嘗試使用自定義註解,註解 Strategy 實現類。

這樣可以簡化原來需在工廠類 List 添加一個 Stratey 策略。

最後

以上就是我在開發中遇到複雜的 if-else 語句“優雅處理”思路,如有不妥,歡迎大家一起交流學習。