22 策略模式

定義

策略模式(Strategy Pattern):定義一系列算法,將每一個算法封裝起來,並讓它們可以相互替換。策略模式算法可以獨立於使用它的客戶而變化。

結構

  1. Context(環境類):環境類是使用算法的角色,它在解決某個問題(即實現某個功能)時可以採用多種策略。在環境類中維持一個對抽象策略類的引用實例,用於定義所採用的策略。
  2. Strategy(抽象決策類):抽象決策類爲所有支持的算法聲明瞭抽象方法,是所有策略類的父類,他可以是抽象類或具體類,也可以是接口。環境類通過抽象策略類中聲明的方法在運行時調用具體策略中實現算法。
  3. ConcreteStrategy(具體策略類):具體策略類實現了在抽象策略類中聲明的方法,在運行時具體策略類將覆蓋在環境類中定義的抽象策略類對象,使用一個具體的算法實現某個業務功能。

代碼

AbstractStrategy

public abstract class AbstractStrategy {
    
    // 聲明抽象算法
    public abstract void algorithm();
    
}

ConcreteStrategyA

public class ConcreteStrategyA extends AbstractStrategy {

    @Override
    public void algorithm() {
        // 算法A
    }

}

ConcreteStrategyB

public class ConcreteStrategyB extends AbstractStrategy {

    @Override
    public void algorithm() {
        // 算法B
    }

}

Context

public class Context {

    private AbstractStrategy strategy;

    // 調用策略類中方法
    public void algorithm() {
        strategy.algorithm();
    }

    public void setStrategy(AbstractStrategy strategy) {
        this.strategy = strategy;
    }
    
}

Test

public class Test {

    public static void main(String[] args) {
        Context context = new Context();
        context.setStrategy(new ConcreteStrategyA());
        context.algorithm();
    }

}

優/缺點與適用環境

  1. 優點
  • 策略模式提供了對開閉原則的完美支持,用戶可以在不修改原有系統的基礎上選擇算法或行爲,也可以靈活地增加新的算法或行爲。
  • 策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行爲族,恰當地使用繼承可以把公共的代碼移到抽象策略類中,從而避免重複的代碼。
  • 策略模式提供了一種可以替換繼承關係的辦法。如果不使用策略模式,那麼使用算法的環境類就可能會有一些子類,每一個子類提供一種不同的算法。但是這樣一來算法的使用就和算法本身混在一起,不符合單一職責原則,決定使用哪種算法的邏輯和該算法本身混合在一起,從而不可能再獨立演化;而且使用繼承無法實現算法或行爲在程序運行時的動態切換。
  • 使用策略模式可以避免多重條件選擇語句。多重條件選擇語句不易維護,它把採取哪一種算法或行爲的邏輯與算法或行爲本身的實現邏輯混合在一起,將它們全部硬編碼在一個龐大的多重條件選擇語句中,比直接繼承環境類的辦法還要原始和落後。
  • 策略模式提供了一種算法的複用機制,由於將算法單獨提取出來封裝在策略類中,因此不同的環境類可以方便地複用這些策略類。
  1. 缺點
  • 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類,這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法。換而言之,策略模式只適用於客戶端知道所有算法或行爲的情況。
  • 策略模式將造成系統產生很多具體策略類,任何細小的變化都將導致系統要增加一個新的具體策略類,
  • 無法同時在客戶端使用多個策略類,也就是說,在使用策略模式時客戶端每次只能使用一個策略類,不支持使用一個策略類完成部分功能後再使用另一個策略類完成功能的情況。
  1. 適用環境
  • 一個系統需要動態地在幾種算法中選擇一種,那麼可以將這些算法封裝到一個個的具體算法類中,而這些具體算法類都是一個抽象算法類的子類。換而言之,這些具體算法類均有統一的接口,根據里氏代換原則和麪向對象的多態性,客戶端可以選擇使用任何一個具體算法類,並只需要維持一個數據類型是抽象算法類的對象。
  • 一個對象有很多行爲,如果不用恰當的模式,這些行爲則只好使用多重條件選擇語句來實現。此時使用策略模式把這些行爲轉移到相應的具體策略類裏面,就可以避免使用難以維護的多重條件選擇語句。
  • 不希望客戶端知道複雜的、與算法相關的數據結構,在具體策略類中封裝算法與相關的數據結構,可以提高算法的保密性與安全性。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章