參考:https://www.cnblogs.com/lewis0077/p/5133812.html(深入解析策略模式) 參考:https://www.cnblogs.com/lewis0077/p/5133812.html(深入解析策略模式) 定義: 策略模式定義了一系列的演算法,並將每一個演算法封 ...
參考:https://www.cnblogs.com/lewis0077/p/5133812.html(深入解析策略模式)
定義:
策略模式定義了一系列的演算法,並將每一個演算法封裝起來,使每個演算法可以相互替代,使演算法本身和使用演算法的客戶端分割開來,相互獨立。結構:(書中的圖,侵刪)
1.一個定義公共方法的介面
2.若幹實現了介面的具體實現
3.上下文context,用於跟客戶端和策略之間交互
例子:
經過我的思考,我感覺上一篇的簡單工廠模式使用的計算器的例子,似乎用在這裡更為恰當吧。 我們的目的是選擇不同的演算法,而不是創建不同的對象。 但其實兩者的表現形式很像,只是用途不同。 所以,我這裡繼續用計算器的例子。(書中用的是商戶採取不同的優惠策略的例子)公共介面:
package designpattern.strategy; public interface Calculate { public double calculate(double num1, double num2); }
具體實現(加減乘除方法):
package designpattern.strategy; public class Plus implements Calculate { @Override public double calculate(double num1, double num2) { return num1 + num2; } }
package designpattern.strategy; public class Minus implements Calculate { @Override public double calculate(double num1, double num2) { return num1 - num2; } }
package designpattern.strategy; public class Multiply implements Calculate { @Override public double calculate(double num1, double num2) { return num1 * num2; } }
package designpattern.strategy; public class Divide implements Calculate { @Override public double calculate(double num1, double num2) { return num1 / num2; } }
上下文:
package designpattern.strategy; public class CalculateContext { Calculate calculate; public CalculateContext(Calculate calculate) { super(); this.calculate = calculate; } public double calculate(double num1, double num2) { return calculate.calculate(num1, num2); } }
客戶端:
package designpattern.strategy; import java.util.Scanner; public class Calculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("請輸入一個數字"); double num1 = scanner.nextDouble(); System.out.println("請輸入一個運算符:+、-、*、/"); String operator = scanner.next();// 不能用nextLine(),會把上一個回車給吸收 System.out.println("請輸入一個數字"); double num2 = scanner.nextDouble(); switch (operator) { case "+": System.out.println(new CalculateContext(new Plus()).calculate(num1, num2)); break; case "-": System.out.println(new CalculateContext(new Minus()).calculate(num1, num2)); break; case "*": System.out.println(new CalculateContext(new Multiply()).calculate(num1, num2)); break; case "/": System.out.println(new CalculateContext(new Divide()).calculate(num1, num2)); break; default: break; } scanner.close(); } }
這樣的寫法,還是把判斷的任務交給了客戶端。
可以稍加改善,把判斷交給上下文context。
上下文:
package designpattern.strategy; public class CalculateContext2 { Calculate calculate; public CalculateContext2(String operate) { super(); switch (operate) { case "+": this.calculate = new Plus(); break; case "-": this.calculate = new Minus(); break; case "*": this.calculate = new Multiply(); break; case "/": this.calculate = new Divide(); break; } } public double calculate(double num1, double num2) { return calculate.calculate(num1, num2); } }
客戶端:
package designpattern.strategy; import java.util.Scanner; public class Calculator2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("請輸入一個數字"); double num1 = scanner.nextDouble(); System.out.println("請輸入一個運算符:+、-、*、/"); String operator = scanner.next();// 不能用nextLine(),會把上一個回車給吸收 System.out.println("請輸入一個數字"); double num2 = scanner.nextDouble(); System.out.println(new CalculateContext2(operator).calculate(num1, num2)); scanner.close(); } }
這裡使用了簡單工廠模式的思想,傳入一個參數,不管具體細節,獲得所期望的對象,所以算是簡單工廠模式和策略模式的結合。
總結:
策略模式能將我們從if-else中解放出來,當我們需要不停的寫if-else的時候,可以想起策略模式。讓我們的代碼可擴展且更易於維護。