Java 設計模式—策略模式
在閻宏博士的《JAVA與模式》一書中開頭是這樣描述策略(Strategy)模式的:
策略模式屬於對象的行為模式。其用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。
策略模式把一個系列的算法封裝到一個系列的具體策略類裏面,作為一個抽象策略類的子類或策略接口的實現類。簡單地說:準備一組算法,並將每一個算法封裝起來,使它們可以互換。
示意性UML圖:
這個模式涉及到3個角色:
環境(Context)角色:持有一個Strategy抽象策略類或策略接口的引用。
抽象策略(Strategy)角色:這是一個抽象角色,由一個接口或抽象類實現。此角色聲明所有的具體策略類需要重寫的方法。
具體策略(Concrete Strategy)角色:封裝了相關的算法或行為。
示意性實例:
環境角色
1 public class Context { 2 // 持有一個具體策略的對象 3 private Strategy strategy; 4 /** 5 * 構造函數,傳入一個具體策略對象 6 * @param strategy 具體策略對象 7 */ 8 public Context(Strategy strategy){ 9 this.strategy = strategy;10 } 11 /** 12 * 策略方法 13 */ 14 public void contextInterface(){ 15 16 strategy.strategyInterface(); 17 } 18 19 }
抽象策略角色
1 public interface Strategy { 2 /** 3 * 策略方法 4 */ 5 public void strategyInterface(); 6 }
具體策略角色
1 public class ConcreteStrategyA implementsStrategy { 2 3 @Override 4 public void strategyInterface() { 5 // 相關的業務 6 } 7 8 }
1 public class ConcreteStrategyB implements Strategy { 2 3 @Override 4 public void strategyInterface() { 5 // 相關的業務 6 } 7 8 }
1 public class ConcreteStrategyC implements Strategy { 2 3 @Override 4 public void strategyInterface() { 5 // 相關的業務 6 } 7 8 }
使用場景實例:
假設某個網站銷售各種書籍,對初級會員沒有提供折扣,對中級會員提供每本10%的促銷折扣,對高級會員提供每本20%的促銷折扣。
折扣是根據以下的3個算法中的1個進行的:
算法1:對初級會員沒有提供折扣。
算法2:對中級會員提供10%的促銷折扣。
算法3:對高級會員提供20%的促銷折扣。
該實例的UML圖:
折扣接口
1 public interface MemberStrategy { 2 /** 3 * 計算圖書的價格 4 * @param booksPrice 圖書的原價 5 * @return 計算出打折後的價格 6 */ 7 public double calcPrice(double booksPrice); 8 }
初級會員折扣實現類
1 public class PrimaryMemberStrategy implements MemberStrategy { 2 3 @Override 4 public double calcPrice(double booksPrice) { 5 6 System.out.println("對於初級會員的沒有折扣"); 7 return booksPrice; 8 } 9 10 }
中級會員折扣實現類
1 public class IntermediateMemberStrategy implements MemberStrategy { 2 3 @Override 4 public double calcPrice(double booksPrice) { 5 6 System.out.println("對於中級會員的折扣為10%"); 7 return booksPrice * 0.9; 8 } 9 10 }
高級會員折扣實現類
1 public class AdvancedMemberStrategy implements MemberStrategy { 2 3 @Override 4 public double calcPrice(double booksPrice) { 5 6 System.out.println("對於高級會員的折扣為20%"); 7 return booksPrice * 0.8; 8 } 9 }
價格類
1 public class Price { 2 // 持有一個具體的策略對象 3 private MemberStrategy strategy; 4 /** 5 * 構造函數,傳入一個具體的策略對象 6 * @param strategy 具體的策略對象 7 */ 8 public Price(MemberStrategy strategy){ 9 this.strategy = strategy; 10 } 11 12 /** 13 * 計算圖書的價格 14 * @param booksPrice 圖書的原價 15 * @return 計算出打折後的價格 16 */ 17 public double quote(double booksPrice){ 18 return this.strategy.calcPrice(booksPrice); 19 } 20 }
客戶端
1 public class Client { 2 3 public static void main(String[] args) { 4 // 選擇並創建需要使用的策略對象 5 MemberStrategy strategy = new AdvancedMemberStrategy(); 6 // 創建環境 7 Price price = new Price(strategy); 8 // 計算價格 9 double quote = price.quote(300); 10 System.out.println("圖書的最終價格為:" + quote); 11 } 12 13 }
策略模式的重心不是如何實現算法,而是如何組織、調用這些算法,從而讓程序結構更靈活,具有更好的維護性和擴展性。策略算法是相同行為的不同實現。在運行期間,策略模式在每一個時刻只能使用一個具體的策略實現對象。把所有的具體策略實現類的共同公有方法封裝到抽象類裏面,將代碼向繼承等級結構的上方集中。
策略模式優點:
1 通過策略類的等級結構來管理算法族。
2 避免使用將采用哪個算法的選擇與算法本身的實現混合在一起的多重條件(if-else if-else)語句。
策略模式缺點:
1 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。
2 由於策略模式把每個算法的具體實現都單獨封裝成類,針對不同的情況生成的對象就會變得很多。
參考資料
《JAVA與模式》之策略模式
Java 設計模式—策略模式