設(shè)計模式之二——策略模式

原文傳送門

1 介紹

1.1 什么是策略模式

策略模式簡單的說就是,準(zhǔn)備一組算法,并將每一個算法封裝起來,使得它們可以互換。
策略模式是一種對象行為型模式。

1.2 解決什么樣的問題

策略模式為了解決什么樣的問題呢?我們來看一個例子。

超市隔三差五就要辦促銷活動,每次促銷活動的方式不一樣,希望找到一種方式,使得營業(yè)員只要輸入原價再選擇活動類型后,就能計算出折扣以后的價錢。

面對這個問題,通常我們想到的解決方案是用if...else或者switch語句寫出邏輯分支。這樣做會有兩個問題:

  1. 如果要增加新的折扣方式,就打破的"開-閉"原則。
    2.業(yè)務(wù)邏輯不能復(fù)用。
    時間久了這段代碼會漸漸成為面條代碼,環(huán)境和行為會緊密耦合在一起,逐漸腐敗,難以維護(hù)。

2 原理

2.1 UML圖

  • 類圖


    image.png

類圖清晰的表明了策略模式結(jié)構(gòu)的參與者。

  1. Strategy:定義所有支持的算法的公共接口。Context使用這個接口來調(diào)用某ConcreteStrategy定義的算法。
  2. ConcreteStrategy:具體策略。以Strategy接口實現(xiàn)某具體算法。
  3. Context:上下文,用一個ConcreteStrategy對象來配置;維護(hù)一個對Strategy對象的引用;可定義一個接口來讓Strategy訪問它的數(shù)據(jù)。
  • 時序圖


    image.png

2.2 代碼示例

Context示例代碼

public class Context{
    private Strategy strategy;

    Context(Strategy strategy){
        this.strategy = strategy;
    }

    public void contextInterface(){
        strategy.strategyInterface();
    }

}

Strategy示例代碼

public interface Strategy { //這里用接口描述, 也可以使用抽象類

    void strategyInterface();
}

ConcreteStrategy示例代碼

public class ConcreteStrategyA implements Strategy {

    @Override
    public void strategyInterface() {
        System.out.println("this is ConcreteStrategyA "); 
    }
}

調(diào)用示例

public static void main(String[] args) {
        Strategy strategyA = new ConcreteStrategyA();
        Context context = new Context(strategyA);
        context.contextInterface();
    }

運行結(jié)果

this is ConcreteStrategyA 

2.3 優(yōu)缺點

  • 優(yōu)點

    • 非常易于擴(kuò)展
      策略模式提供了對“開閉原則”的完美支持,用戶可以在不修改原有系統(tǒng)的基礎(chǔ)上選擇算法(策略),并且可以靈活地增加新的算法(策略)。
    • 避免使用多重條件轉(zhuǎn)移語句。
    • 算法可以自由切換。
  • 缺點

    • 客戶端必須知道所有得策略類,并自行決定使用哪一個策略類。這使得策略類定義必須暴露給客戶端。
    • 造成很多策略類,帶來額外的維護(hù)開銷,如果策略類超過4個,就需要考慮使用混合模式,解決策略類膨脹的問題。

4 適用場景

在以下情況下可以使用策略模式

  1. 如果在一個系統(tǒng)里面有許多類,它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動態(tài)地讓一個對象在許多行為中選擇一種行為。
  2. 一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種。
  3. 如果一個對象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行為就只好使用多重的條件選擇語句來實現(xiàn)。
  4. 不希望客戶端知道復(fù)雜的、與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu),在具體策略類中封裝算法和相關(guān)的數(shù)據(jù)結(jié)構(gòu),提高算法的保密性與安全性。

5 總結(jié)

5.1 設(shè)計原則

  • "開-閉"原則。策略模式是"開-閉"原則的一個極好的應(yīng)用范例。
  • 里氏代換原則。里氏代換原則是策略模式的基礎(chǔ)。策略模式要求所有的策略對象都是可以互換的,因此它們都必須是一個抽象策略角色的子類。在客戶端則僅知道抽象策略角色類型,雖然變量的真實類型可以是任何一個具體策略角色的實例。

5.2 認(rèn)識策略模式

  • 策略模式的重心

策略模式的重心不是如何實現(xiàn)算法,而是如何組織、調(diào)用這些算法,從而讓程序結(jié)構(gòu)更靈活,具有更好的維護(hù)性和擴(kuò)展性。

  • 算法的平等性

策略模式一個很大的特點就是各個策略算法的平等性。對于一系列具體的策略算法,大家的地位是完全一樣的,正因為這個平等性,才能實現(xiàn)算法之間可以相互替換。所有的策略算法在實現(xiàn)上也是相互獨立的,相互之間是沒有依賴的。

所以可以這樣描述這一系列策略算法:策略算法是相同行為的不同實現(xiàn)。

  • 運行時策略的唯一性

運行期間,策略模式在每一個時刻只能使用一個具體的策略實現(xiàn)對象,雖然可以動態(tài)地在不同的策略實現(xiàn)中切換,但是同時只能使用一個。

  • 公有的行為

經(jīng)常見到的是,所有的具體策略類都有一些公有的行為。這時候,就應(yīng)當(dāng)把這些公有的行為放到共同的抽象策略角色Strategy類里面。當(dāng)然這時候抽象策略角色必須要用Java抽象類實現(xiàn),而不能使用接口。

這其實也是典型的將代碼向繼承等級結(jié)構(gòu)的上方集中的標(biāo)準(zhǔn)做法。


image.png

參考書籍和文章

  1. 《Java與模式》,電子工業(yè)出版社,閻宏
  2. 《設(shè)計模式——可復(fù)用面向?qū)ο筌浖幕A(chǔ)》,機(jī)械工業(yè)出版社,Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides
  3. 《圖說設(shè)計模式》,https://design-patterns.readthedocs.io/zh_CN/latest/index.html
  4. 《 < JAVA與模式 > 之策略模式》,https://www.cnblogs.com/java-my-life/archive/2012/05/10/2491891.html
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • javascript設(shè)計模式與開發(fā)實踐 設(shè)計模式 每個設(shè)計模式我們需要從三點問題入手: 定義 作用 用法與實現(xiàn) 單...
    穿牛仔褲的蚊子閱讀 4,489評論 0 13
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是策略模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 策略模式和模板方法模式的區(qū)別 優(yōu)點和...
    w1992wishes閱讀 961評論 1 7
  • 本文僅僅為入門,高手勿噴。 實際工作中,我們總會遇到類似如下的需求:某支付系統(tǒng)接入以下幾種商戶進(jìn)行充值:易寶網(wǎng)易,...
    JarvanMo閱讀 14,375評論 14 26
  • 1.初識策略模式 定義一系列的算法,把它們一個個封裝起來,并且使它們可相互替換。本模式使得算法可獨立于使用它的客戶...
    王偵閱讀 1,545評論 0 3
  • 二十三種設(shè)計模式 - 策略模式 策略模式簡介 模式動機(jī) 完成一項任務(wù),往往可以有多種不同的方式,每一種方式稱為一個...
    JustTheSame閱讀 1,903評論 2 16

友情鏈接更多精彩內(nèi)容