参考: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的时候,可以想起策略模式。让我们的代码可扩展且更易于维护。