什么是策略模式:
- 策略模式是一种比较简单的模式,也叫政策模式。
- 策略模式使用的就是面向对象的继承和多态机制。
- 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
- 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
策略模式中的三个角色:
- context:封装角色
一般称之为上下文,起着承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。 - strategy:抽象策略角色
策略、算法的抽象,通常为借口,定义每个策略或算法必须具有的方法和属性。 - concreteStrategy:具体策略角色
- 实现抽象策略中的操作,即具体实现
优缺点:
优点:
- 算法可以自由切换
- 避免使用多重条件判断
- 扩展性良好
- 这些算法定义一个公共的接口,以约束这些算法的功能实现。如果这些算法具有公共的功能,可以将接口变为抽象类,将公共功能放到抽象父类里面。
- 策略模式的一系列算法是可以相互替换的、是平等的,写在一起就是if-else组织结构,如果算法实现里又有条件语句,就构成了多重条件语句,可以用策略模式,避免这样的多重条件语句。
- 扩展性更好:在策略模式中扩展策略实现非常的容易,只要新增一个策略实现类,然后在使用策略实现的地方,使用这个新的策略实现就好了。
缺点:
- 策略类数量增多
- 所有的策略类都需要对外暴露
- 客户端必须了解所有的策略,清楚它们的不同:
- 如果由客户端来决定使用何种算法,那客户端必须知道所有的策略,清楚各个策略的功能和不同,这样才能做出正确的选择,但是这暴露了策略的具体实现。
- 增加了对象的数量:
- 由于策略模式将每个具体的算法都单独封装为一个策略类,如果可选的策略有很多的话,那对象的数量也会很多。
- 只适合偏平的算法结构:
- 由于策略模式的各个策略实现是平等的关系(可相互替换),实际上就构成了一个扁平的算法结构。即一个策略接口下面有多个平等的策略实现(多个策略实现是兄弟关系),并且运行时只能有一个算法被使用。这就限制了算法的使用层级,且不能被嵌套。
使用场景:
- 多个类只有在算法或行为上稍有不同的场景
- 算法需要自由切换的场景
- 需要屏蔽算法规则的场景
注意:
如果一个策略模式具体策略数量超过4个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题
代码示例:
// 上下文
public class ConsumerContext {
private Consumer consumer;
ConsumerContext(Consumer consumer) {
this.consumer = consumer;
}
public void bill() {
consumer.discount();
}
}
// 策略角色
public interface Consumer {
void discount();
}
public class NewConsumer implements Consumer {
@Override
public void discount() {
System.out.println("新用户今天搞活动,满500打9.8折");
}
}
public class OldConsumer implements Consumer {
@Override
public void discount() {
System.out.println("老顾客打9折");
}
}
public class VIPConsumer implements Consumer {
@Override
public void discount() {
System.out.println("VIP 顾客打8折");
}
}