一、策略模式的定義
策略(Strategy)模式的定義:該模式定義了一系列算法,並將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬於對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,並委派給不同的對象對這些算法進行管理。
二、策略模式優缺點
策略模式的主要優點如下。
- 多重條件語句不易維護,而使用策略模式可以避免使用多重條件轉移語句。
- 符合開閉原則,可以在不修改原代碼的情況下,靈活增加新算法。
- 算法使用和實現隔離分離,提高算法的保密性和安全性。
- 策略模式提供了一系列的可供重用的算法族,恰當使用繼承可以把算法族的公共代碼轉移到父類里面,從而避免重復的代碼。
- 策略模式可以提供相同行為的不同實現,客戶可以根據不同時間或空間要求選擇不同的。
其主要缺點如下。
- 客戶端必須理解所有策略算法的區別,以便適時選擇恰當的算法類。
- 策略模式造成很多的策略類。
三、策略模式的結構與實現
策略模式是准備一組算法,並將這組算法封裝到一系列的策略類里面,作為一個抽象策略類的子類。策略模式的重心不是如何實現算法,而是如何組織這些算法,從而讓程序結構更加靈活,具有更好的維護性和擴展性,現在我們來分析其基本結構和實現方法。
策略模式的主要角色如下。
- 抽象策略(Strategy)類:定義了一個公共接口,各種不同的算法以不同的方式實現這個接口,環境角色使用這個接口調用不同的算法,一般使用接口或抽象類實現。
- 具體策略(Concrete Strategy)類:實現了抽象策略定義的接口,提供具體的算法實現。
- 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。
其結構圖如圖所示:
代碼實現如下:
public class StrategyPattern { public static void main(String[] args) { Context c=new Context(); Strategy s=new ConcreteStrategyA(); c.setStrategy(s); c.strategyMethod(); System.out.println("-----------------"); s=new ConcreteStrategyB(); c.setStrategy(s); c.strategyMethod(); } } //抽象策略類 interface Strategy { public void strategyMethod(); //策略方法 } //具體策略類A class ConcreteStrategyA implements Strategy { public void strategyMethod() { System.out.println("具體策略A的策略方法被訪問!"); } } //具體策略類B class ConcreteStrategyB implements Strategy { public void strategyMethod() { System.out.println("具體策略B的策略方法被訪問!"); } } //環境類 class Context { private Strategy strategy; public Strategy getStrategy() { return strategy; } public void setStrategy(Strategy strategy) { this.strategy=strategy; } public void strategyMethod() { strategy.strategyMethod(); } }
測試結果如下:
具體策略A的策略方法被訪問! ----------------- 具體策略B的策略方法被訪問!
如下補充一個促銷策略模式:
interface PromotionStrategy { void doPromotion(); } class FanXianPromotionStrategy implements PromotionStrategy{ @Override public void doPromotion() { System.out.println("返現促銷"); } } class LiJianPromotionStrategy implements PromotionStrategy { @Override public void doPromotion() { System.out.println("立減促銷"); } } class ManJianPromotionStrategy implements PromotionStrategy{ @Override public void doPromotion() { System.out.println("滿減促銷"); } } class PromotionActivity { private PromotionStrategy promotionStrategy; public PromotionActivity(PromotionStrategy promotionStrategy) { this.promotionStrategy = promotionStrategy; } public void executePromotionStrategy(){ promotionStrategy.doPromotion(); } } public class Test { public static void main(String[] args) { PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy()); PromotionActivity promotionActivity1111 = new PromotionActivity(new FanXianPromotionStrategy()); promotionActivity618.executePromotionStrategy(); promotionActivity1111.executePromotionStrategy(); } }
四、策略模式的應用場景
策略模式在很多地方用到,如 Java SE 中的容器布局管理就是一個典型的實例,Java SE 中的每個容器都存在多種布局供用戶選擇。在程序設計中,通常在以下幾種情況中使用策略模式較多。
- 一個系統需要動態地在幾種算法中選擇一種時,可將每個算法封裝到策略類中。
- 一個類定義了多種行為,並且這些行為在這個類的操作中以多個條件語句的形式出現,可將每個條件分支移入它們各自的策略類中以代替這些條件語句。
- 系統中各算法彼此完全獨立,且要求對客戶隱藏具體算法的實現細節時。
- 系統要求使用算法的客戶不應該知道其操作的數據時,可使用策略模式來隱藏與算法相關的數據結構。
- 多個類只區別在表現行為不同,可以使用策略模式,在運行時動態選擇具體要執行的行為。
五、策略模式的擴展
在一個使用策略模式的系統中,當存在的策略很多時,客戶端管理所有策略算法將變得很復雜,如果在環境類中使用策略工廠模式來管理這些策略類將大大減少客戶端的工作復雜度,其結構圖如圖所示: