策略模式 Strategy 政策Policy 行為型 設計模式(二十五)


策略模式 Strategy
image_5c21cbb4_55b2
 
image_5c21cbb4_3b5
與策略相關的常見詞匯有:營銷策略、折扣策略、教學策略、記憶策略、學習策略....
“策略”意味着分情況討論,而不是一概而論
面對不同年齡段的人,面對不同的商品,必然將會有不同的話術;
面對購物總價的范圍,很可能會有不同的折扣方案;
面對理解能力不同的學生,必然有不同的教學策略;
 
而在我們程序的世界里,“策略”就是分情況討論。也就是 類似狀態模式中的條件分支或者選擇分支
只不過 狀態模式中是事物的不同狀態,而策略模式中關注的是處理方法
比如
if(totalPrice > 1000){
//9折
else if(totalPrice > 2000){
//8折
}else if(totalPrice > 3000){
//7折
}
這就是一種打折策略,對應於購物總金額的不同,采用不同的處理方法。
顯然,使用條件分支或者選擇語句,類似狀態模式中的分析,也存在類似的問題
如果條件過多,會導致 處理邏輯復雜
而且,策略的邏輯與業務邏輯 耦合在一起,如果處理方法變化還需要修改業務邏輯方法, 擴展性差
而且,也 不適合增加新的策略方案

意圖

定義一系列的算法,把他們一個個的封裝起來,並使他們可以互相轉換,本模式使得算法可以獨立於使用它的客戶端而變化。
別名:政策Policy
策略模式與狀態模式本質一樣,只不過一個是狀態,一個是行為算法。

結構

image_5c21cbb4_22ad
抽象策略角色Strategy
定義了抽象的策略,比如打折,排序等
定義了策略的一致性訪問接口,比如定義了一個排序接口 sort()
具體策略角色ConcreteStrategy
實現抽象策略的定義的接口,實現自己的行為算法,比如ConcreteStrategyA冒泡 ConcreteStrategyB快排
環境類Context
維護Strategy,持有一個Strategy的引用,用來管理Strategy,可以切換策略
是Strategy的使用者

代碼示例

排序接口,定義了一個sort方法
package strategy;
public interface SortStrategy {
void sort();
}
package strategy;
public class Bubble implements SortStrategy {
    @Override
    public void sort() {
        System.out.println("冒泡排序,輸出結果...");
    }
}
package strategy;
public class QuickSort implements SortStrategy {
    @Override
    public void sort() {
        System.out.println("快速排序,輸出結果...");
    }
}
環境類
內部持有一個SortStrategy,簡單起見初始化為Bubble
使用一個簡單的方法進行切換
並且提供sort方法,代理strategy的sort方法
package strategy;
public class Context {
    private SortStrategy strategy = new Bubble();
    public void setStrategy(String strategy) {
        if(strategy.equals("bubble")){
            this.strategy = new Bubble();
        }else if(strategy.equals("quick")){
            this.strategy = new QuickSort();
        }
    }
    public void sort() {
        strategy.sort();
    }
}
測試方法
package strategy;
public class Test {
public static void main(String[] args) {
    Context context = new Context();
    context.sort();
    context.setStrategy("quick");
    context.sort();
    context.setStrategy("bubble");
    context.sort();
    }
}

 

image_5c21cbb4_406f
上面的代碼可以看得出來,具體的算法行為,被封裝在了具體的策略類中,比如Bubble和QuickSort
通過環境類Context對算法進行管理切換。

總結

策略模式與狀態模式是類似的,借助於多態的特性,以達到不同狀態不同行為
不同的場景使用不同的算法,這本就是一種“不同狀態,不同行為”的含義延伸
都是借助於多態特性,進而也就是依賴倒置原則---面向抽象編程,其根本也是為了“低耦合”。
 
策略模式中使用獨立的類來封裝不同的算法行為,每一個類封裝具體的行為
策略模式主要是將 算法的定義與使用進行分開,算法被封裝在不同的策略類中
借助於算法的環境類Context,針對抽象策略進行編程,符合依賴倒置原則 
而且,新增加具體的算法,只需要增加一個新的具體的策略類即可。
 
策略模式將算法的定義與使用分開,具體的策略完全可以通過配置文件等方式注入到Context中,客戶端完全不需要關注具體的策略
而且, 運行時可以隨時的更換策略
 
策略模式的Context,我們的示例中一個Context一個當前策略,那么Context到底內部維護幾個策略?到底誰負責切換,是客戶端還是Context
個人認為都是靈活的,策略模式的核心就在於算法的定義與使用的解耦,在接下來的其他事情,自己看情況隨便來(隨便的前提是合理有效)
 
只要是涉及到 多種算法行為
切換:策略可以運行時切換
復用:算法與使用解耦,算法可以單獨擴展
封裝:屏蔽使用者對算法內部數據結構等邏輯的了解,否則如果算法的實現耦合在客戶端,客戶端不是一清二楚么
可以考慮策略模式,策略模式能夠靈活的切換算法,以及算法獨立發展,符合開閉原則 
 
但是類似狀態模式,策略模式也會產生很多小的具體的策略類,增加類的個數和運行時對象的個數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM