策略模式Strategy Pattern
在Java的集合框架中,經常需要通過構造方法傳入一個比較器Comparator,或者創建比較器傳入Collections的靜態方法中作為方法參數,進行比較排序等,使用的是策略模式。
策略模式的定義
定義一組算法,將每個算法都封裝起來,並且使它們之間可以互換。
策略模式使這些算法在客戶端調用它們的時候能夠互不影響地變化。
體現了兩個非常基本的面向對象設計原則:
封裝變化的概念。
編程中使用接口,而不是對接口的實現。
策略模式的意義
策略模式使開發人員能夠開發出由許多可替換的部分組成的軟件,並且各個部分之間是弱連接的關系。
弱連接的特性使軟件具有更強的可擴展性,易於維護;更重要的是,它大大提高了軟件的可重用性。
策略模式的組成
抽象策略角色:策略類,通常由一個接口或者抽象類實現。
具體策略角色:包裝了相關的算法和行為。
環境角色:持有一個策略類的引用,最終給客戶端用的。
策略模式的實現
策略模式的用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以互相替換。
策略模式使得算法可以在不影響到客戶端的情況下發生變化。使用策略模式可以把行為和環境分割開來。
環境類負責維持和查詢行為類,各種算法則在具體策略中提供。由於算法和環境獨立開來,算法的修改不會影響環境和客戶端。
策略模式的編寫步驟
1.對策略對象定義一個公共接口。
2.編寫策略類,該類實現了上面的公共接口。
3.在使用策略對象的類中保存一個對策略對象的引用。
4.在使用策略對象的類中,實現對策略對象的set和get方法(注入)或者使用構造方法完成賦值。
運用策略模式的例子
定義一個Strategy接口,其中定義一個方法,用於計算。
public interface Strategy { public int calculate(int a, int b); }
定義具體的算法類,實現Strategy接口,算法類中的算法各自不同:加減乘等,但是外部調用形式符合接口的定義。
public class AddStrategy implements Strategy { @Override public int calculate(int a, int b) { return a + b; } }
public class SubtractStrategy implements Strategy { @Override public int calculate(int a, int b) { return a - b; } }
public class MultiplyStrategy implements Strategy { @Override public int calculate(int a, int b) { return a * b; } }
定義具體的環境角色,持有Strategy接口的引用,並且有get和set方法可以完成策略更換。在環境角色中調用接口的方法完成動作。
public class Environment { private Strategy strategy; public Environment(Strategy strategy) { this.strategy = strategy; } public Strategy getStrategy() { return strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public int calculate(int a, int b) { return strategy.calculate(a, b); } }
這樣在Client外部調用時,只需向環境角色設置相應的算法類,然后就可以得到相應的結果。
public class Client { public static void main(String[] args) { AddStrategy addStrategy = new AddStrategy(); Environment environment = new Environment(addStrategy); System.out.println(environment.calculate(4, 3)); //減法 SubtractStrategy subStrategy = new SubtractStrategy(); environment.setStrategy(subStrategy); System.out.println(environment.calculate(4, 3)); //乘法 MultiplyStrategy multiplyStrategy = new MultiplyStrategy(); environment.setStrategy(multiplyStrategy); System.out.println(environment.calculate(4, 3)); } }
策略模式的缺點
1.客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。
2.造成很多的策略類。
解決方案:采用工廠方法。
參考資料
聖思園張龍老師Java SE教學視頻《Java SE 第五十一講 策略模式深度剖析及其在集合框架中的應用》。