策略模式 Strategy
與策略相關的常見詞匯有:營銷策略、折扣策略、教學策略、記憶策略、學習策略....
“策略”意味着分情況討論,而不是一概而論
面對不同年齡段的人,面對不同的商品,必然將會有不同的話術;
面對購物總價的范圍,很可能會有不同的折扣方案;
面對理解能力不同的學生,必然有不同的教學策略;
而在我們程序的世界里,“策略”就是分情況討論。也就是
類似狀態模式中的條件分支或者選擇分支。
只不過
狀態模式中是事物的不同狀態,而策略模式中關注的是處理方法。
比如
if(totalPrice > 1000){ //9折 else if(totalPrice > 2000){ //8折 }else if(totalPrice > 3000){ //7折 }
這就是一種打折策略,對應於購物總金額的不同,采用不同的處理方法。
顯然,使用條件分支或者選擇語句,類似狀態模式中的分析,也存在類似的問題
如果條件過多,會導致
處理邏輯復雜
而且,策略的邏輯與業務邏輯
耦合在一起,如果處理方法變化還需要修改業務邏輯方法,
擴展性差
而且,也
不適合增加新的策略方案
意圖
定義一系列的算法,把他們一個個的封裝起來,並使他們可以互相轉換,本模式使得算法可以獨立於使用它的客戶端而變化。
別名:政策Policy
策略模式與狀態模式本質一樣,只不過一個是狀態,一個是行為算法。
結構
抽象策略角色Strategy
定義了抽象的策略,比如打折,排序等
定義了策略的一致性訪問接口,比如定義了一個排序接口 sort()
具體策略角色ConcreteStrategy
實現抽象策略的定義的接口,實現自己的行為算法,比如ConcreteStrategyA冒泡 ConcreteStrategyB快排
環境類Context
維護Strategy,持有一個Strategy的引用,用來管理Strategy,可以切換策略
是Strategy的使用者
代碼示例
排序接口,定義了一個sort方法
package strategy; public interface SortStrategy { void sort(); }
package strategy; public class Bubble implements SortStrategy { @Override public void sort() { System.out.println("冒泡排序,輸出結果..."); } }
package strategy; public class QuickSort implements SortStrategy { @Override public void sort() { System.out.println("快速排序,輸出結果..."); } }
環境類
內部持有一個SortStrategy,簡單起見初始化為Bubble
使用一個簡單的方法進行切換
並且提供sort方法,代理strategy的sort方法
package strategy; public class Context { private SortStrategy strategy = new Bubble(); public void setStrategy(String strategy) { if(strategy.equals("bubble")){ this.strategy = new Bubble(); }else if(strategy.equals("quick")){ this.strategy = new QuickSort(); } } public void sort() { strategy.sort(); } }
測試方法
package strategy; public class Test { public static void main(String[] args) { Context context = new Context(); context.sort(); context.setStrategy("quick"); context.sort(); context.setStrategy("bubble"); context.sort(); } }
上面的代碼可以看得出來,具體的算法行為,被封裝在了具體的策略類中,比如Bubble和QuickSort
通過環境類Context對算法進行管理切換。
總結
策略模式與狀態模式是類似的,借助於多態的特性,以達到不同狀態不同行為
不同的場景使用不同的算法,這本就是一種“不同狀態,不同行為”的含義延伸
都是借助於多態特性,進而也就是依賴倒置原則---面向抽象編程,其根本也是為了“低耦合”。
策略模式中使用獨立的類來封裝不同的算法行為,每一個類封裝具體的行為
策略模式主要是將
算法的定義與使用進行分開,算法被封裝在不同的策略類中
借助於算法的環境類Context,針對抽象策略進行編程,符合依賴倒置原則
而且,新增加具體的算法,只需要增加一個新的具體的策略類即可。
策略模式將算法的定義與使用分開,具體的策略完全可以通過配置文件等方式注入到Context中,客戶端完全不需要關注具體的策略
而且,
運行時可以隨時的更換策略
策略模式的Context,我們的示例中一個Context一個當前策略,那么Context到底內部維護幾個策略?到底誰負責切換,是客戶端還是Context
個人認為都是靈活的,策略模式的核心就在於算法的定義與使用的解耦,在接下來的其他事情,自己看情況隨便來(隨便的前提是合理有效)
只要是涉及到
多種算法行為的
切換:策略可以運行時切換
復用:算法與使用解耦,算法可以單獨擴展
封裝:屏蔽使用者對算法內部數據結構等邏輯的了解,否則如果算法的實現耦合在客戶端,客戶端不是一清二楚么
都
可以考慮策略模式,策略模式能夠靈活的切換算法,以及算法獨立發展,符合開閉原則
但是類似狀態模式,策略模式也會產生很多小的具體的策略類,增加類的個數和運行時對象的個數。




