1、概念
策略模式定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
2、模式结构
- 环境类:也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
- 抽象策略类:通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
- 具体策略类:具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换
3、使用场景
- 几个类的主要逻辑相同,只在部分逻辑的算法和行为上稍有区别的情况
- 一个系统需要动态地在几种算法中选择一种
- 一个对象有很多的行为,如果不使用合适的模式,这些行为就只好使用多重的if-else语句来实现,此时,可以使用策略模式
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性
4、优缺点
优点
- 对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
- 提供了管理相关的算法族的办法
- 提供了可以替换继承关系的办法
- 避免使用多重条件转移语句
缺点
- 维护各个策略类会给开发带来额外开销
- 必须对客户端(调用者)暴露所有的策略类,因为使用哪种策略是由客户端来决定的
5、实例
定义抽象策略角色(Strategy)
public interface Strategy {
public float getPrice(float costPrice);
}
定义具体策略角色(Concrete Strategy)
public class ConcreteStrategyA implements Strategy {
@Override
public float getPrice(float costPrice) {
return costPrice * 0.95f;
}
}
public class ConcreteStrategyB implements Strategy {
@Override
public float getPrice(float costPrice) {
return costPrice - 10;
}
}
定义环境角色(Context):用于连接上下文
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public float getPrice(float costPrice) {
return strategy.getPrice(costPrice);
}
}
客户端使用
float costPrice = 1000f;
ConcreteStrategyA strategyA = new ConcreteStrategyA();
Context context = new Context(strategyA);
context.getPrice(costPrice);