概覽
政策模式定義了一系列算法,并将每個算法封裝起來,使他們可以互相替換,且算法的變化不會影響到使用算法的客戶。需要設計一個接口,為一系列實作類提供統一的方法,多個實作類實作該接口,設計一個抽象類(可有可無,屬于輔助類),提供輔助函數。
政策模式屬于對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實作分割開來,并委派給不同的對象對這些算法進行管理。
在政策模式中,我們建立表示各種政策的對象和一個行為随着政策對象改變而改變的 context 對象。政策對象改變 context 對象的執行算法。
政策模式的優缺點
政策模式的主要優點
- 多重條件語句不易維護,而使用政策模式可以避免使用多重條件語句,如 if...else 語句、switch...case 語句。
- 政策模式提供了一系列的可供重用的算法族,恰當使用繼承可以把算法族的公共代碼轉移到父類裡面,進而避免重複的代碼。
- 政策模式可以提供相同行為的不同實作,客戶可以根據不同時間或空間要求選擇不同的。
- 政策模式提供了對開閉原則的完美支援,可以在不修改原代碼的情況下,靈活增加新算法。
- 政策模式把算法的使用放到環境類中,而算法的實作移到具體政策類中,實作了二者的分離。
其主要缺點
- 用戶端必須了解所有政策算法的差別,以便适時選擇恰當的算法類。
- 政策模式造成很多的政策類,增加維護難度。
政策模式的應用場景
政策模式在很多地方用到,如JavaSE 中的容器布局管理就是一個典型的執行個體,Java SE 中的每個容器都存在多種布局供使用者選擇。在程式設計中,通常在以下幾種情況中使用政策模式較多。
- 一個系統需要動态地在幾種算法中選擇一種時,可将每個算法封裝到政策類中。
- 一個類定義了多種行為,并且這些行為在這個類的操作中以多個條件語句的形式出現,可将每個條件分支移入它們各自的政策類中以代替這些條件語句。
- 系統中各算法彼此完全獨立,且要求對客戶隐藏具體算法的實作細節時。
- 系統要求使用算法的客戶不應該知道其操作的資料時,可使用政策模式來隐藏與算法相關的資料結構。
- 多個類隻差別在表現行為不同,可以使用政策模式,在運作時動态選擇具體要執行的行為。
政策模式的結構與實作
政策模式是準備一組算法,并将這組算法封裝到一系列的政策類裡面,作為一個抽象政策類的子類。政策模式的重心不是如何實作算法,而是如何組織這些算法,進而讓程式結構更加靈活,具有更好的維護性和擴充性。
模式的結構
政策模式的主要角色如下
- 抽象政策(Strategy)類:定義了一個公共接口,各種不同的算法以不同的方式實作這個接口,環境角色使用這個接口調用不同的算法,一般使用接口或抽象類實作。
- 具體政策(Concrete Strategy)類:實作了抽象政策定義的接口,提供具體的算法實作。
- 環境(Context)類:持有一個政策類的引用,最終給用戶端調用。
模式的實作
我們将建立一個定義活動的 Strategy 接口和實作了 Strategy 接口的實體政策類。Context 是一個使用了某種政策的類。
StrategyPatternDemo,我們的示範類使用 Context 和政策對象來示範 Context 在它所配置或使用的政策改變時的行為變化。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuUmNihTYmNGZkVmM5EmZmlDM1ITMkhDMwYWZhlzMwcDMvw1M0UDM4ETOtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
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));
}
}
複制
輸出結果
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
複制
政策模式的擴充
- 在一個使用政策模式的系統中,當存在的政策很多時,用戶端管理所有政策算法将變得很複雜,如果在環境類中使用政策工廠模式來管理這些政策類将大大減少用戶端的工作複雜度。
如果使用的是Spring容器,将每個具體政策類注入到Spring容器中,統一管理,然後在Client使用@Autowire注入到一個Map中。
@Autowire
private Map strategyServiceMap;
複制
提示:Map的key是預設每個具體政策類首字母小寫的字元串,比如:政策類
DemoStrategyServiceImpl
,Map中key為
demoStrategyServiceImpl
,value為具體政策類
總結
優點: 1、算法可以自由切換。 2、避免使用多重條件判斷。 3、擴充性良好。
缺點: 1、政策類會增多。 2、所有政策類都需要對外暴露。
使用場景
1、如果在一個系統裡面有許多類,它們之間的差別僅在于它們的行為,那麼使用政策模式可以動态地讓一個對象在許多行為中選擇一種行為。
2、一個系統需要動态地在幾種算法中選擇一種。
3、如果一個對象有很多的行為,如果不用恰當的模式,這些行為就隻好使用多重的條件選擇語句來實作。
**注意事項:**如果一個系統的政策多于四個,就需要考慮使用混合模式,解決政策類膨脹的問題。