策略模式
在策略模式(Strategy Pattern)中,一個類的行爲或其算法可以在運行時更改,這種類型的設計模式屬於行爲型模式。在策略模式中,我們創建表示多個策略的對象和一個行爲隨着策略對象改變而改變的 context 對象。每個策略對象會改變 context 對象的執行算法。這個描述讀起來有點繞口,接下來筆者還是通過具體應用案例和代碼演示,讀者通過閱讀代碼就可以體會到Java設計模式中策略模式的精髓。
主要解決:在有多種算法或行爲相似的情況下,使用 if...else(或者switch...case) 所帶來的複雜和難以維護。
何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行爲或算法。
如何解決:將這些算法封裝成一個一個的類,任意地替換。
關鍵代碼:通過多態思想,多個策略對象實現同一個接口。
應用實例: 1、諸葛亮的錦囊妙計,每一個錦囊就是一個策略。 2、旅行的出遊方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個策略。
優點: 1、算法可以自由切換。 2、避免使用多重條件判斷。 3、擴展性良好。
缺點: 1、策略類會增多。 2、所有策略類都需要對外暴露。
演示實例:給定一個數值類型的字符串根據前置條件(動態的數據格式)轉換成多種對象類型格式
實現
首先創建一個解析String的接口ParseStrUtil和實現了ParseStrUtil接口的三個策略類。Context 是一個使用了某種策略的類。我們的演示類使用 Context 和策略對象來演示 Context 在它所配置或使用的策略對象改變時的行爲變化。
步驟 1:創建一個接口
public interface ParseStrUtil<T> {
public Class<?> parse(String body);
}
步驟 2:創建實現上述接口的三個策略類
public class IntType implements ParseStrUtil<Object>{
@Override
public Class<? extends Integer> parse(String body) {
return Integer.valueOf(Integer.parseInt(body)).getClass();
}
}
public class LongType implements ParseStrUtil<Object>{
@Override
public Class<? extends Integer> parse(String body) {
return Long.valueOf(Long.parseLong(body)).getClass();
}
}
public class DoubleType implements ParseStrUtil<Object>{
@Override
public Class<? extends Integer> parse(String body) {
return Double.valueOf(Double.parseDouble(body)).getClass();
}
}
步驟 3:創建Context類
public class Context{
private ParseStrUtil<?> body;
public Context(){}
public void setContext(ParseStrUtil<?> json){
this.body = json;
}
public Class<?> parseStr(String str){
return body.parse(str);
}
}
步驟 4:測試,使用 Context 來查看當它改變策略對象時的算法變化
public static void main(String[] args) {
Context context = new Context();
context.setContext(new IntType());
System.out.println("String -->>>" + context.parseStr("20"));
context.setContext(new LongType());
System.out.println("String -->>>" + context.parseStr("20"));
context.setContext(new DoubleType());
System.out.println("String -->>>" + context.parseStr("20"));
System.out.println("可以看到調用的相同的方法傳入的參數是相同的,但是最終轉換後的數據格式是不一樣的");
}
控制檯打印結果:
String -->>>class java.lang.Integer
String -->>>class java.lang.Long
String -->>>class java.lang.Double
可以看到調用的相同的方法傳入的參數是相同的,但是最終轉換後的數據格式是不一樣的
可以看出:策略模式主要是用來封裝一組可以互相替代的算法族,並且可以根據需要動態地去替換 Context 使用的算法或者行爲