一、策略模式
- 策略模式的用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。
換言之,如果我們需要新的方案,我們創建這個方案的類繼承事先定義好的共同接口,然後在使用的時候替換爲此方案就可以了。 - 使用策略模式可以把行爲和環境分割開來。環境類負責維持和查詢行爲類,各種算法則在具體策略類中提供。
- 由於算法和環境獨立開來,算法的增減、修改都不會影響環境和客戶端。當出現新的方案的時候,只需要實現新的策略類,並在客戶端登記即可。策略模式相當於可插入式的算法.
本質:分類算法,選擇實現。
二、涉及角色
-
環境(Context)角色:是一個Strategy類的引用(上下文對象),負責和具體的策略類交互。
在這個類中,承上啓下,類中定義共同接口的接口對象,並用構造函數初始化這個接口對象,不同的策略實現時候初始化不同的方案,也就是實現這個接口對象。還有幾個類方法,在主函數被調用。 -
抽象策略(Strategy)角色:這是一個抽象角色,通過由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
所有的具體算法策略都繼承這個類,此類在Context類中作爲接口對象,由具體策略實現。 -
具體策略(ConcreateStrategy)角色:包裝了相關的算法或行爲。
三、策略模式簡單實例
使用策略模式實現計算器相關內容。
抽象策略角色
public interface Strategy {
public int doOperation(int num1, int num2);
}
具體策略角色
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
環境角色
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
主函數
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
四、使用情況
- 出現同一個算法,有很多不同的實現的情況,可以使用策略模式來把這些“不同的實現”實現成爲一個算法的類層次。(計算器中的加減乘除、商店的不同打折方案等)。
- 出現抽象一個定義了很多行爲的類,並且是通過多個if-else語句來選擇這些行爲的情況,可以使用策略模式來代替這些條件語句。(在寫程序中,比較忌諱的是許多條件分支語句)
五、優點與缺點
優點
- 策略模式可以避免讓客戶端涉及到不必要的接觸到複雜的和只與算法有關的數據。
- 避免使用難以維護的多重條件選擇語句。
- 更好的擴展
缺點
- 上述策略模式,把分支判斷又放回到客戶端,要改變需求算法時,還是要去更改客戶端的程序。
- 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。(實現計算器的時候,我必須知道加減乘除對應哪些的實現類,比較麻煩)
- 增加了對象的數目。(從策略類接口到策略類,還有環境類,使程序變得更加複雜了)
- 只適合扁平的算法結構。