Java程式員從笨鳥到菜鳥之(三十四)大話設計模式(四)策略模式

來源:互聯網
上載者:User

        本文來自:曹勝歡部落格專欄。轉載請註明出處:http://blog.csdn.net/csh624366188

 

          Strategy是屬於設計模式中 對象行為型模式,主要是定義一系列的演算法,把這些演算法一個個封裝成單獨的類。

定義:策略模式定義了一系列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。(原文:The Strategy Pattern defines a family ofalgorithms,encapsulates each one,and makes them interchangeable. Strategy
letsthe algorithm vary independently from clients that use it.)

角色:

Strategy:策略介面,用來約束一系列具體的策略演算法。Context使用這個介面來調用具體的策略實現定義的演算法。

ConcreteStrategy:具體的策略實現,也就是具體的演算法實現。

Context:上下文,負責和具體的策略類互動,通常上下文會持有一個真正的策略實現,上下文還可以讓具體的策略類來擷取內容相關的資料,甚至讓具體的策略類來回調內容相關的方法。

策略模式的結構1所示:


應用情境:

  1、 多個類只區別在表現行為不同,可以使用Strategy模式,在運行時動態選擇具體要執行的行為。

  2、 需要在不同情況下使用不同的策略(演算法),或者策略還可能在未來用其它方式來實現。

  3、 對客戶隱藏具體策略(演算法)的實現細節,彼此完全獨立。

優點:

1、 簡化了單元測試,因為每個演算法都有自己的類,可以通過自己的介面單獨測試。
  2、 避免程式中使用多重條件轉移語句,使系統更靈活,並易於擴充。
    3、 遵守大部分GRASP原則和常用設計原則,高內聚、低偶合。

4.提供了一種替代繼承的方法,而且既保持了繼承的優點(代碼重用)還比繼承更靈活(演算法獨立,可以任意擴充)。

缺點:
  1、 因為每個具體策略類都會產生一個新類,所以會增加系統需要維護的類的數量。
    2、 在基本的策略模式中,選擇所用具體實現的職責由用戶端對象承擔,並轉給策略模式的Context對象。(這本身沒有解除用戶端需要選擇判斷的壓力,而策略 模式與簡單原廠模式結合後,選擇具體實現的職責也可以由Context來承擔,這就最大化的減輕了用戶端的壓力。)

舉一個我看過的策略模式比較經典的例子:報價管理

對不同的客戶要報不同的價格,向客戶報價是非常複雜的,因此在一些CRM(客戶關係管理)的系統中,會有一個單獨的報價管理模組,來處理複雜的報價功能。

為了示範的簡潔性,假定現在需要實現一個簡化的報價管理,實現如下的功能:

(1)對普通客戶或者是新客戶報全價

(2)對老客戶報的價格,統一折扣5%

(3)對大客戶報的價格,統一折扣10%

(1)先看策略介面,範例程式碼如下: 

/** * 策略,定義計算報價演算法的介面 */public interface Strategy {    /**     * 計算應報的價格     * @param goodsPrice 商品銷售原價     * @return 計算出來的,應該給客戶報的價格     */    public double calcPrice(double goodsPrice);}

(2)接下來看看具體的演算法實現,不同的演算法,實現也不一樣,先看為新客戶或者是普通客戶計算應報的價格的實現,範例程式碼如下: 

/** * 具體演算法實現,為新客戶或者是普通客戶計算應報的價格 */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);    }}

(3)接下來看看內容相關的實現,也就是原來的價格類,它的變化比較大,主要有:

  • 原來那些私人的,用來做不同計算的方法,已經去掉了,獨立出去做成了演算法類
  • 原來報價方法裡面,對具體計算方式的判斷,去掉了,讓用戶端來完成選擇具體演算法的功能
  • 新添加持有一個具體的演算法實現,通過構造方法傳入
  • 原來報價方法的實現,變化成了轉調具體演算法來實現

範例程式碼如下: 

/** * 價格管理,主要完成計算向客戶所報價格的功能 */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);    }}

(4)寫個用戶端來測試回合一下,好加深體會,範例程式碼如下:  

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);    }}

 

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.