定义
策略模式是一种行为型模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
特点
1)一组算法,那就是不同的策略。
2)这组算法都实现了相同的接口或者继承相同的抽象类,所以可以相互切换。
UML图
这个模式涉及到三个角色:
- 环境(Context)角色:持有一个Strategy的引用,即具有复杂多变行为的对象。对策略进行二次封装,目的是避免高层模块对策略的直接调用
- 抽象策略(Strategy)角色:通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
- 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为,具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。
Context中contextInterface()方法是调用抽象策略角色(Strategy接口的声明方法),多态的思想:通过Java的多态,调用对应策略子类的方法。
具体实现
举例: 在电子商务网站中给不同等级的会员提供不同的优惠折扣
折扣策略接口
public interface DiscountStrategy {
void calcPrice();
}
初级会员折扣类
public class PrimaryDiscountStrategy implements DiscountStrategy {
@Override
public void calcPrice() {
System.out.println("对初级会员计算折扣");
}
}
中级会员折扣类
public class IntermediateDiscountStrategy implements DiscountStrategy {
@Override
public void calcPrice() {
System.out.println("对中级会员计算折扣");
}
}
高级会员折扣类
public class AdvancedDiscountStrategy implements DiscountStrategy {
@Override
public void calcPrice() {
System.out.println("对高级会员计算折扣");
}
}
环境角色
public class PriceContext {
private DiscountStrategy strategy;
/**
* 构造函数 传入一个具体的策略对象
* @param strategy
*/
public PriceContext(DiscountStrategy strategy){
this.strategy = strategy;
}
public void discountCalc() {
strategy.calcPrice();
}
}
具体调用
public class Client {
public static void main(String[] args) {
DiscountStrategy strategy = new AdvancedDiscountStrategy();
PriceContext context = new PriceContext(strategy);
context.discountCalc();
}
}
输出:对高级会员计算折扣
策略模式的优缺点
优点
- 支持“开闭原则”,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为,提供了管理相关的算法族的办法。
- 使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况
- 由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。
总结
策略模式的重点不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。
适用场景:
1.如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2.一个系统需要动态地在几种算法中选择一种。
3.如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。