策略模式
1.定义
策略模式(Strategy)作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.
2.认识策略模式
- 策略模式的功能
策略模式的功能是把具体的算法实现,从具体的业务处理里面独立出来,实现成为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换.
策略模式的重心不是如何来实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活、具有更好的维护性和扩展性.
- 策略模式和if-else语句
每个策略算法具体实现的功能,就是原来if-else结构中的具体实现.其实多个if-else语句表达的就是一个平等的功能结构,你要么执行if,要不你就执行else,或者是elseif,这个时候,if块里面的实现和else块里面的实现从运行地位上来讲就是平等的.
而策略模式就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下文来与具体的策略类进行交互.
因此多个if-else语句可以考虑使用策略模式.
- 算法的平等性
策略模式一个很大的特点就是各个策略算法的平等性.对于一系列具体的策略算法,大家的地位是完全一样的,正是因为这个平等性,才能实现算法之间可以相互替换.
所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的.
所以可以这样描述一系列策略算法: 策略算法是相同行为的不同实现.
- 谁来选择具体的策略算法
在策略模式中,可以在两个地方来进行具体策略的选择.
一个是在客户端,在使用上下文的时候,由客户端来选择具体的策略算法,然后把这个策略算法设置给上下文.
还有一个是客户端不管,由上下文来选择具体的策略算法.
- Strategy的实现方式
Strategy都是使用接口来定义的,这也是常见的实现方式.但是如果多个算法具有公共功能的话,可以把Strategy实现成为抽象类,然后把多个算法的公共功能实现到Strategy里面.
- 运行时策略的唯一性
运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态的在不同的策略实现中切换,但是同时只能使用一个.
- 增加新的策略
策略模式中切换算法是很方便的,但是增加一个新的算法会怎样呢?
其实很简单,策略模式可以让你很灵活的扩展新的算法.具体的做法是: 先写一个策略算法类来实现新的要求,然后在客户端使用的时候指定使用新的策略算法类就可以了.
3.实现
策略模式(Strategy)
- 环境(Context)角色
- 抽象策略(Strategy)角色
- 具体策略(Concrete Strategy)角色

环境(Context)角色: 对策略进行二次封装,目的是避免高层模块对策略的直接调用
/**
* 环境(Context)角色
*/
public class Context {
private Strategy strategy;
// Constructor
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void execute() {
this.strategy.execute();
}
}
抽象策略(Strategy)角色: 提供具体策略类所需的统一接口
/**
* 抽象策略(Strategy)角色
*/
public interface Strategy {
void execute();
}
具体策略(Concrete Strategy)角色: 包装了相关的算法或行为
/**
* 具体策略(Concrete Strategy)角色
*/
// Implements the algorithm using the strategy interface
public class FirstStrategy implements Strategy {
public void execute() {
System.out.println("Called FirstStrategy.execute()");
}
}
/**
* 具体策略(Concrete Strategy)角色
*/
// Implements the algorithm using the strategy interface
public class SecondStrategy implements Strategy {
public void execute() {
System.out.println("Called SecondStrategy.execute()");
}
}
测试客户端
/**
* 测试客户端
*/
public class StrategyClient {
public static void main(String[] args) {
Context context = new Context(new FirstStrategy());
context.execute();
context = new Context(new SecondStrategy());
context.execute();
// stdout
// Called FirstStrategy.execute()
// Called SecondStrategy.execute()
}
}
4.总结
优缺点
- 定义一系列算法
- 避免多重条件语句
- 更好的扩展性
- 客户必须了解每种策略的不同
- 增加了对象数目
- 只适合扁平的算法结构
对设计原则的体现 从设计原则上来看,策略模式很好的体现了开-闭原则.策略模式通过把一系列可变的算法进行封装,并定义出合理的使用结构,使得在系统出现新算法的时候,能很容易的把新的算法加入到已有的系统中,而已有的实现不需要做任何修改.
从设计原则上来看,策略模式还很好的体现了历史替换原则.策略模式是一个扁平结构,一系列的实现算法其实是兄弟关系,都是实现同一个接口或者继承的同一个父类.这样只要使用策略的客户保持面向抽象类型编程,就能够使用不同的策略的具体实现对象来配置它,从而实现一系列算法可以相互替换.
何时选用
- 出现有许多相关的类,仅仅是行为有差别的情况,可以使用策略模式来使用多个行为中的一个来配置一个类的方法,实现算法动态切换
- 出现同一个算法,有很多不同的实现的情况,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次
- 需要封装算法中,与算法相关的数据的情况,可以使用策略模式来避免暴漏这些跟算法相关的数据结构
- 出现抽象一个定义了很多行为的类,并且是通过多个if-else语句来选择这些行为的情况,可以使用策略模式来代替这些条件语句.