不一樣的策略模式(設計模式五)
前言
什麼是設計模式?說白了就是套路,是經過歷代程式設計師總結出來的。很多時候我們雖然學會了很多套路,但是啥時候使用,使用哪個合適,我想這才是問題的關鍵。
知道怎麼用不知道什麼時候用,這時候看下程式碼風格也行用的上,策略模式是非常容易通過程式碼風格使用上的。
策略模式,為什麼叫策略模式呢?其實策略模式還有一個別名叫做政策(policy)模式,在古代,對不同的國家呢,實行不同的政策,對A呢,採取稅務10%,對B國採取稅務20%。
這樣根據不同國家政策不同呢,在計算機中就是根據不同物件採取不同的方法,就叫做策略模式咯。但是呢,如果直接採用if else 這種行為呢,人們發現過於臃腫,且複用性極差,那麼就形成了這樣一種模式去緩解這個問題。
那麼策略模式的風格是什麼,檢視正文。
開車出發
public enum PolicyBase { US_Policy, DE_Policy, FR_Policy } public class Strategy { PolicyBase policyBase; public Strategy(PolicyBase policyBase) { this.policyBase = policyBase; } public double CalculatePolicy() { if (policyBase == PolicyBase.US_Policy) { return 0.9; } else if (policyBase == PolicyBase.DE_Policy) { return 0.8; } else if (policyBase == PolicyBase.FR_Policy) { return 0.1; } return 0; } }
根據不同的國家,採取了不同的政策。這樣一看好像沒有啥問題啊,根據了不同國家制定了不同稅法。
但是呢,在開發程式碼的時間軸上,也就是未來的角度上存在的極大的問題。比如和英國(GB)合作了,我得改吧?然後又和另外一個國家合作了,恐怕又得來一遍。
這時候有人就納悶了,還想不改程式碼?程式碼的確是要改的,但是不能違法了封閉開發原則。
在紅色部分呢,是我們需要繼續往下新增程式碼的地方,也就是我們加一個國家就需要把我們寫過的任何一個區域改一遍。
我想這就很糟糕了,牽扯太大,對於釋出來說就需要測試整個子模組,我想這代價無法讓人接受,這時候策略者模式就出現了。
public enum PolicyBase { US_Policy, DE_Policy, FR_Policy } public interface Policy { double Calculate(); } public class USPolicy : Policy { public double Calculate() { throw new NotImplementedException(); } } public class DEPolicy : Policy { public double Calculate() { throw new NotImplementedException(); } } public class FRPolicy : Policy { public double Calculate() { throw new NotImplementedException(); } } public class StrategyFactory{ Policy policy; public StrategyFactory(PolicyBase policyBase) { switch (policyBase) { case PolicyBase.US_Policy: policy = new USPolicy(); break; case PolicyBase.DE_Policy: policy = new DEPolicy(); break; case PolicyBase.FR_Policy: policy = new FRPolicy(); break; } } public Policy GetPolicy() { return policy; } } class SalesOrder { private Policy Policy; public SalesOrder(StrategyFactory strategyFactory) { this.Policy = strategyFactory.GetPolicy(); } public double CalculatePolicy() { double val = Policy.Calculate(); return val; } };
上述程式碼中,通過策略者模式把原來的獲取各國的稅法比例變成了SalesOrder類,而這個類不再改變,也就是說所以依賴於獲取各國稅法引數的將依賴於一個穩定的類。
這時候很多納悶了,如果我需要新增一個英國(GB),依然需要在紅色部分就行修改啊,修改的地方如下:
修改的地方一樣多,且還要多加一個GBPolicy類,這不是白忙活了嗎?
首先我們來看下前後依賴關係圖:
使用策略模式前:
使用策略模式後:
這樣一看,不僅是沒有啥好處,還複雜了。
然而這樣一想,我們處理的是解決這個稅法問題這個業務上,可以肯定的就是使用策略模式後,我下面紅框部分穩定了,也就是在二進位制上可以複用,但是上面紅色部分倒是有問題了,耦合太大。
但是呢,我們知道上面複雜部分其實就是簡單工廠模式,問題就回到了如何優化簡單工廠模式了,如果能解決上面紅框的問題,那麼是可行的。
由於篇幅有限,下一篇總結工廠模式到抽象工廠到反射這個演化。
這時候我們看到了,如果遇到了if else 且以後會增加else if,可以用策略模式,去緩解這個問題,增加程式碼複用性。
但是穩定的if else 呢是不需要的,比如說星期一到星期日,這種就是穩定的了,本來處於穩定的,那麼其改變的價值就不是很大。
uml圖
後續補上
總結
策略模式的作用,解決使用不穩定 的if...else 所帶來的複雜和難以維護