这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
一、概念
策略模式(Strategy Pattern)作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。 比如视频网站用户看视频的时,普通用户、会员、超级会员、限定会员“享受”的广告时间,选择的视频质量是大不相同。 简单点说,策略模式是指定义了算法家族、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户,策略模式是一种对象行为模式。
所以策略模式的特征为:
- 定义了一族算法(业务规则);
- 封装了每个算法;
- 这族的算法可互换代替(interchangeable)。
二、代码模型
所谓策略模型,肯定是包含了一众多策略算法,我们先定义一个抽象的策略Strategy。
public interface Strategy {
/**
* strategy details
*/
void strategyImplementation();
}
针对这个抽象策略,我们提供一些不同的实现类。
DefaultStrategy
class DefaultStrategy implements Strategy {
/**
* strategy details
*/
@Override
public void strategyImplementation() {
System.out.println("default strategy");
}
}
AnotherStrategy
class AnotherStrategy implements Strategy {
/**
* strategy details
*/
@Override
public void strategyImplementation() {
System.out.println("another strategy");
}
}
策略算法我们准备好了,那客户端怎么方便使用它们呢?当然是用一个Context套住它。
public class Context {
Strategy strategy = null;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void doStrategy() {
strategy.strategyImplementation();
}
}
具体客户端使用的方法。
public static void main(String[] args) {
final Context context = new Context(new DefaultStrategy());
context.doStrategy();
final Context anotherContext = new Context(new AnotherStrategy());
anotherContext.doStrategy();
}
往往我们在生产环境中不会这样使用,为啥呢?因为往往我们都是根据实际需求动态选择策略,而不是一次性执行多个策略。
修改一下客户端使用方式,通过获取一个策略点,来进行动态地分配策略。
static void doStrategy(String strategyPoint){
Context context;
if(strategyPoint.equals("default")){
context = new Context(new DefaultStrategy());
}else if(strategyPoint.equals("another")){
context = new Context(new AnotherStrategy());
}else{
throw new IllegalArgumentException("Unknown strategy");
}
context.doStrategy();
}
可以很清楚地看到,如果后期策略不断的增加,这段逻辑也会不断地修改,那么怎么办呢,下一篇文章我们讲到如何使用工厂模式+策略模式优化这部分代码。
三、总结
那策略模式适合哪些应用场景呢?
- 假如系统中有很多类,而它们的区别仅仅在于他们的行为不同。
- 一个系统需要动态地在几种算法中选择一种。
策略模式强调的因为业务场景的动态变化,需要引入模式进行管理,如果本身你的算法极少发生改变,那确实没有必要引入策略模式,强行引入会增加代码量、逻辑的复杂度。
而且策略模式对于使用者来说也不是特别友好,因为它要选择不同的策略,所以它必须知道各个策略的差异性。