模式定义
定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。
主要作用(解决的问题)
将算法的责任和本身进行解耦,使得:
- 算法可独立于使用外部而变化。
- 客户端方便根据外部条件选择不同策略来解决不同问题。
模式原理
UML类图
模式优点
- 策略类之间可以自由切换
由于策略类都实现同一个接口,所以使它们之间可以自由切换。 - 易于扩展
增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“。 - 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。
模式缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
应用场景
如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。
一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。
如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。
模式示例
示例背景
背景:假设有一家百货公司,最近在定年度的促销活动
冲突:每个节日用同一个促销活动太枯燥,没吸引力
解决方案:针对不同节目使用不同促销活动进行促销
使用步骤
定义抽象策略角色(Strategy)
百货公司所有促销活动的共同接口
1 | package main.java.com.study.designPatterns.strategy.demoOne; |
定义具体策略角色(Concrete Strategy)
春节促销活动
1 | package main.java.com.study.designPatterns.strategy.demoOne; |
中秋促销活动
1 | package main.java.com.study.designPatterns.strategy.demoOne; |
圣诞促销活动
1 | package main.java.com.study.designPatterns.strategy.demoOne; |
定义环境角色(Context)
用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员
1 | package main.java.com.study.designPatterns.strategy.demoOne; |
客户端调用
让销售员进行促销活动的落地
1 | package main.java.com.study.designPatterns.strategy.demoOne; |