策略模式
模式名和分类
- 策略模式:xxxStrategy
- 分类:行为模式
意图
解决处理算法多变而程序设计改动需要小的矛盾。就是算法的增加和修改,程序的影响更小。
别名
xxxPolicy
动机
-
解决多变的处理算法,而不愿意改动太多程序。
面对经常变化的算法需求,可能是电商系统中多变的优惠需求,支付系统中可能是不同分类商户的处理方式,经常新增的邮件模板..等等。在算法不确定且多变,而我们只需要选择其中之一时,不妨考虑此模式。 -
如果你的程序中用了过多的case,或者过多的if-else,目的是根据条件选择不同的处理算法。
-
如果你的处理算法需要经常变动,需要时常新增。
-
如果你需要根据不同的条件路由到不同的处理方式
结构
参与者
- 抽象接口/类,它代表着一类问题的抽象表达。例如计算,加法计算,减法计算或是其他类计算,都是传入值得到结果。--Strategy
- 具体处理算法类,它将实现/继承抽象的接口或类,作为真正的执行者。--Add、Substract、Multiply
- 运行环境,它将保存上下文环境,真正的做出选择,根据条件选择具体的算法类处理问题。--Context
协作
-
调用者创建运行环境类Context
-
在context中聚合了Strategy接口
-
当调用者执行
Context.doOperation
时,context选择具体的Strategy实现者来处理问题。 -
调用端不需要直接耦合算法类,构建合适的context后,只需要调用
Context.doOperation
得到结果。 -
增加算法:只需要实现Strategy接口,然后再调用方来构建对应的Context即可。
-
替换算法:调用者构建不同的context,context即会调用算法。
-
路由算法:可以再创建Context时通过构造函数由调用者指定具体的路由算法(案例代码就是这么做的),也可以传入选择条件让Context来根据条件选择具体的路由算法(例如工厂模式或者直接if-else判断)。
实现
- 算法抽象类,代表一类的处理方法。
- 上下文context作为模式的运行环境
- 调用者,构建context时选择需要的算法,可能时构造函数注入,也可能时传入条件让context自己判断。
代码实例
https://www.runoob.com/design-pattern/strategy-pattern.html
如果有写得好的例子,为什么不能抄呢,毕竟你写得不一定有他好
模式案例
// Strategy.java 接口
public interface Strategy {
public int doOperation(int num1, int num2);
}
// OperationAdd.java 具体策略:加法
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
// OperationSubstract.java 具体策略:减法
public class OperationSubstract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
// OperationMultiply.java 具体策略:乘法
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
// Context.java 运行环境:保存策略的上下文
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);
}
}
// StrategyPatternDemo.java 调用者:使用策略。这里值得提一下,此处在构建context的时候直接由构造函数
// 指定了具体策略,但是我们在应用的时候,可以不这么简单粗暴。
// 跟不同的模式,例如工厂、抽象工厂、建造者模式之类的模式配合起来,可以更灵活,封装得更好。根据具体需要来选择
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 OperationSubstract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
已知应用
spring框架中:InstantiationStrategy
在spring框架中,没有找到好的实现Strategy的例子,在jmx中有提到,但是不够经典。在springMVC中,它的实现方式更多,但是用法多半不单单限于策略模式,或者说不能完美的展示这个模式,暂时不太愿意在这里详细展示。希望以后写到其他模式的时候,或者混合模式的时候能记起来,这里还留了一个空。但是...老话说得好“later equals never”。