定義
策略模式(Strategy Pattern)是一種比較簡單的模式,也叫政策模式(Policy Pattern)。其定義如下:
Define a family of algorithms, encapsulate each one, and make them interchangeable.
定義一組算法,將每個算法都封裝起來,並且使它們之間可以互換。
重點: 定義一組算法
,封裝
, 算法之間可互換
。
策略模式的通用模型類圖如下:
- Context封裝角色
它作爲上下文角色,承上啓下的封裝作用,屏蔽高層模塊對策略、算法的直接訪問,封裝可能存在的變化。 - Strategy抽象策略角色
策略、算法家族的抽象,通常爲接口,定義每個策略或算法必須具有的方法和屬性。其中AlgorithmInterface
爲算法的‘運算法則’。 - ConcreteStrategy具體策略角色
實現抽象策略中的操作,該類含有具體的算法。
模板代碼:
// 抽象的策略角色
public interface Strategy {
// 策略模式的運算法則
public void algorithmInterface();
}
// 具體策略角色
public class ConcreteStrategy1 implements Strategy {
public void algorithmInterface() {
// 具體策略1的運算法則
}
}
// 封裝角色
public class Context {
// 抽象策略
private Strategy strategy = null;
// 構造函數設置具體策略
public Context(Strategy _strategy) {
this.strategy = _strategy;
}
// 封裝後的策略方法
public void doAnything() {
this.strategy.algorithmInterface();
}
}
最終高層模塊的調用非常簡單,知道要用哪個策略,產生出它的對象,然後放到封裝角色中就完成任務了,如下代碼:
public class Client {
public static void main(String[] args) {
// 聲明一個具體的策略
Strategy strategy = new ConcreteStrategy1();
// 聲明上下文對象
Context context = new Context(Strategy);
// 執行封裝後的方法
}
}
策略模式就是這麼簡單。
策略模式的優點
- 策略可以自由的切換
只要實現抽象策略,它就成爲策略家族的一個成員,通過封裝角色對其進行封裝,保證對外提供“可自由切換”的策略。 - 避免使用多重條件判斷
使用策略模式後,可以由其他模塊決定採用何種策略,策略家族對外提供的訪問接口就是封裝類,簡化了操作,同時避免了條件語句判斷。 - 擴展性良好
它就像一個可以反覆拆卸的插件,這大大地符合了OCP原則。
策略模式的缺點
- 策略類數量增多
每一個策略都是一個類,複用的可能性很小,類數量增多。 - 所有的策略類都需要對外暴露
上層模塊必須知道有哪些策略,然後才能決定使用哪一個策略,這與迪米法則
是相違背的。我只想使用一個策略,爲什麼要了解這個策略呢?這是原裝策略模式的一個缺點,不過我們可以使用工廠方法模式、代理模式或享元模式來修正這個缺陷。
策略模式的使用場景
- 多個類只有在算法或行爲上稍有不同的場景
- 算法需要自由切換的場景
- 需要屏蔽算法規則的場景
策略模式的注意事項
如果系統中的一個策略家族的具體策略數量超過4個,則需要考慮使用混合模式,解決策略類膨脹和對外暴露的問題,否則日後的系統維護就會成爲一個誰也不想接的燙手山芋~~