1.策略(Strategy)模式的定義
- 策略模式的用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。
2.策略模式的主要優缺點
優點:
- 多重條件語句不易維護,而使用策略模式可以避免使用多重條件語句。
- 策略模式提供了一系列的可供重用的算法族,恰當使用繼承可以把算法族的公共代碼轉移到父類里面,從而避免重復的代碼。
- 策略模式可以提供相同行為的不同實現,客戶可以根據不同時間或空間要求選擇不同的。
- 策略模式提供了對開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
- 策略模式把算法的使用放到環境類中,而算法的實現移到具體策略類中,實現了二者的分離。
缺點:
- 客戶端必須理解所有策略算法的區別,以便適時選擇恰當的算法類。
- 策略模式造成很多的策略類。
3.策略模式的主要角色
- 抽象策略(Strategy)類:定義了一個公共接口,各種不同的算法以不同的方式實現這個接口,環境角色使用這個接口調用不同的算法,一般使用接口或抽象類實現。
- 具體策略(Concrete Strategy)類:實現了抽象策略定義的接口,提供具體的算法實現。
- 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。
4.策略模式的結構圖
5.策略模式的實現,以購買車為例
- 創建購買汽車策略接口。抽象策略(Strategy)類
package com.lw.designpattern.strategy; /** * @Classname CarStrategy * @Description 汽車策略接口 * @Author lw * @Date 2019-12-25 12:43 */ public interface CarStrategy { public void buyCar(); }
- 創建購買奔馳車類,實現CarStrategy接口。具體策略(Concrete Strategy)類
package com.lw.designpattern.strategy; /** * @Classname BcCar * @Description 奔馳車具體策略類 * @Author lw * @Date 2019-12-25 12:45 */ public class BcCar implements CarStrategy { @Override public void buyCar() { System.out.println("歡迎購買奔馳E300L。。。。。。"); } }
- 創建購買寶馬車類,實現CarStrategy接口。具體策略(Concrete Strategy)類
package com.lw.designpattern.strategy; /** * @Classname BmwCar * @Description 寶馬車具體策略類 * @Author lw * @Date 2019-12-25 12:46 */ public class BmwCar implements CarStrategy { @Override public void buyCar() { System.out.println("歡迎購買寶馬530Li。。。。。。"); } }
- 創建購買奧迪車類,實現CarStrategy接口。具體策略(Concrete Strategy)類
package com.lw.designpattern.strategy; /** * @Classname AudiCar * @Description 奧迪車具體策略類 * @Author lw * @Date 2019-12-25 12:46 */ public class AudiCar implements CarStrategy { @Override public void buyCar() { System.out.println("歡迎購買奧迪A6L。。。。。。"); } }
- 創建汽車環境類。環境(Context)類
package com.lw.designpattern.strategy; /** * @Classname CarContext * @Description 汽車環境類 * @Author lw * @Date 2019-12-25 12:49 */ public class CarContext { private CarStrategy carStrategy; public CarContext(CarStrategy carStrategy){ this.carStrategy = carStrategy; } public void buyCarStrategy(){ carStrategy.buyCar(); } }
- 單元測試
/** * 策略模式 */ @Test public void testStrategy(){ // 寶馬車 CarContext bmwCarContext = new CarContext(new BmwCar()); bmwCarContext.buyCarStrategy(); // 奔馳車 CarContext bcCarContext = new CarContext(new BcCar()); bcCarContext.buyCarStrategy(); // 奧迪車 CarContext audiCarContext = new CarContext(new AudiCar()); audiCarContext.buyCarStrategy(); }
打印結果
6.策略模式的應用場景
- 一個系統需要動態地在幾種算法中選擇一種時,可將每個算法封裝到策略類中。
- 一個類定義了多種行為,並且這些行為在這個類的操作中以多個條件語句的形式出現,可將每個條件分支移入它們各自的策略類中以代替這些條件語句。
- 系統中各算法彼此完全獨立,且要求對客戶隱藏具體算法的實現細節時。
- 系統要求使用算法的客戶不應該知道其操作的數據時,可使用策略模式來隱藏與算法相關的數據結構。
- 多個類只區別在表現行為不同,可以使用策略模式,在運行時動態選擇具體要執行的行為。