策略模式 定義了演算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。 說明: 1、可以動態地改變對象的行為; 2、各個策略演算法的平等性,各個策略演算法在實現上是相互獨立的,相互之間沒有任何依賴的(由此,策略模式也可以描述為“策略演算法是相同行為的不同實現”); 3、在運 ...
策略模式 定義了演算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。 說明: 1、可以動態地改變對象的行為; 2、各個策略演算法的平等性,各個策略演算法在實現上是相互獨立的,相互之間沒有任何依賴的(由此,策略模式也可以描述為“策略演算法是相同行為的不同實現”); 3、在運行期間,策略模式在某一時刻,只能使用一個具體的策略演算法實現對象,雖然可以動態改變對象行為,但同時只能使用一個; 4、策略模式可以很簡單的擴展新的實現演算法。方法:先寫一個策略演算法來實現新的需求,然後在客戶端使用時指定該實現演算法即可; 5、多個if-elseif語句表達的就是一個平等的功能結構,你要麼執行if,要不你就執行else,或者是elseif,這個時候,if塊裡面的實現和else塊裡面的實現從運行地位上來講就是平等的。而策略模式就是把各個平等的具體實現封裝到單獨的策略實現類了,然後通過上下文來與具體的策略類進行交互。因此多個if-else語句可以考慮使用策略模式。 場景: 1、報價管理系統中,對於銷售部門的人來說,要對不同的客戶報不同的價格。如:對於普通用戶或者新用戶來說,報全價;對老客戶報的價格,統一折扣5%;大客戶報的價格,統一折扣10%。 實現: A:定義策略介面
/** * 策略,定義計算報價演算法的介面 */ public interface Strategy { /** * 計算應報的價格 * @param goodsPrice 商品銷售原價 * @return 計算出來的,應該給客戶報的價格 */ public double calcPrice(double goodsPrice); } |
/** * 具體演算法實現,為新客戶或者是普通客戶計算應報的價格 */ public class NormalCustomerStrategy implements Strategy{ public double calcPrice(double goodsPrice) { System.out.println("對於新客戶或者是普通客戶,沒有折扣"); return goodsPrice; } } |
/** * 具體演算法實現,為老客戶計算應報的價格 */ public class OldCustomerStrategy implements Strategy{ public double calcPrice(double goodsPrice) { System.out.println("對於老客戶,統一折扣5%"); return goodsPrice*(1-0.05); } } |
/** * 具體演算法實現,為大客戶計算應報的價格 */ public class LargeCustomerStrategy implements Strategy{ public double calcPrice(double goodsPrice) { System.out.println("對於大客戶,統一折扣10%"); return goodsPrice*(1-0.1); } } |
/** * 價格管理,主要完成計算向客戶所報價格的功能 */ public class Price { /** * 持有一個具體的策略對象 */ private Strategy strategy = null; /** * 構造方法,傳入一個具體的策略對象 * @param aStrategy 具體的策略對象 */ public Price(Strategy aStrategy){ this.strategy = aStrategy; } /** * 報價,計算對客戶的報價 * @param goodsPrice 商品銷售原價 * @return 計算出來的,應該給客戶報的價格 */ public double quote(double goodsPrice){ return this.strategy.calcPrice(goodsPrice); } } |
public class Client { public static void main(String[] args) { //1:選擇並創建需要使用的策略對象 Strategy strategy = new LargeCustomerStrategy (); //2:創建上下文 Price ctx = new Price(strategy); //3:計算報價 double quote = ctx.quote(1000); System.out.println("向客戶報價:"+quote); } } |
/** * 日誌記錄策略的介面 */ public interface LogStrategy { /** * 記錄日誌 * @param msg 需記錄的日誌信息 */ public void log(String msg); } |
(2)實現日誌策略介面,先實現預設的資料庫實現,假設如果日誌的長度超過長度就出錯,製造錯誤的是一個最常見的運行期錯誤,示例代碼如下:
/** * 把日誌記錄到資料庫 */ public class DbLog implements LogStrategy{ public void log(String msg) { //製造錯誤 if(msg!=null && msg.trim().length()>5){ int a = 5/0; } System.out.println("現在把 '"+msg+"' 記錄到資料庫中"); } } |
接下來實現記錄日誌到文件中去,示例代碼如下:
/** * 把日誌記錄到文件 */ public class FileLog implements LogStrategy{ public void log(String msg) { System.out.println("現在把 '"+msg+"' 記錄到文件中"); } } |
(3)接下來定義使用這些策略的上下文,註意這次是在上下文裡面實現具體策略演算法的選擇,所以不需要客戶端來指定具體的策略演算法了,示例代碼如下:
(4)看看現在的客戶端,沒有了選擇具體實現策略演算法的工作,變得非常簡單,故意多調用一次,可以看出不同的效果,示例代碼如下:
參考資料:《Head First 設計模式》 http://www.uml.org.cn/sjms/201009092.asp