简介
策略模式:策略模式是一种行为型模式,它将对象和行为分开,将行为定义为 一个行为接口 和 具体行为的实现。策略模式最大的特点是行为的变化,行为之间可以相互替换,每个if判断都可以理解为就是一个策略,本模式使得算法可独立于使用它的用户而变化。
结构
策略模式包含如下角色:
Strategy:
抽象策略类:策略是一个接口,该接口定义若干个算法标识,即定义了若干个抽象方法(如下图的algorithm())
Context: 环境类 /上下文类:
上下文是依赖于接口的类(是面向策略设计的类,如下图Context类),即上下文包含用策略(接口)声明的变量(如下图的strategy成员变量)。
上下文提供一个方法(如下图Context类中的的lookAlgorithm()方法),持有一个策略类的引用,最终给客户端调用。该方法委托策略变量调用具体策略所实现的策略接口中的方法(实现接口的类重写策略(接口)中的方法,来完成具体功能)
ConcreteStrategy: 具体策略类:
具体策略是实现策略接口的类(如下图的ConcreteStrategyA类和ConcreteStrategyB类)。具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体方法。(说白了就是重写策略类的方法!)

代码
接口类
public interface SeasonsStrategy {
/**
* 根据季节执行不同方案
*
* @param seasons
* @return
*/
String execute(String seasons);
}
策略类
@Component("spring")
public class SpringStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "来了,我们一起去放风筝吧";
}
}
@Component("summer")
public class SummerStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "来了,我们一起去游泳吧";
}
}
@Component("autumn")
public class AutumnStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "来了,我们一起去看枫叶吧";
}
}
@Component("winter")
public class WinterStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "来了,我们一起去堆雪人吧";
}
}
枚举类
public enum SeasonsEnum {
SRPING(1, "spring", "春天"),
SUMMER(2, "summer", "夏天"),
AUTUMN(3, "autumn", "秋天"),
WINTER(4, "winter", "冬天");;
private int code;
private String en;
private String zh;
public int getCode() {
return code;
}
public String getEn() {
return en;
}
public String getZh() {
return zh;
}
SeasonsEnum(int code, String en, String zh) {
this.code = code;
this.en = en;
this.zh = zh;
}
public static SeasonsEnum getByCode(Integer code) {
return Arrays.stream(SeasonsEnum.values()).filter(a -> a.getCode() == code).findFirst().orElse(null);
}
}
工厂类
@Component
public class SeasonsFactory {
/**
* Spring会自动将strategy接口的实现类注入到这个map中,key为bean id ,value值则为对应的策略实现类
*/
@Resource
private Map<String, SeasonsStrategy> strategy;
/**
* 统一入口
*
* @param seasons
* @return
*/
public String handle(SeasonsEnum seasons) {
SeasonsStrategy seasonsStrategy = strategy.get(seasons.getEn());
return seasonsStrategy.execute(seasons.getZh());
}
}
测试类
@RestController
@RequestMapping("/strategy")
public class StrategyController {
@Resource
private SeasonsFactory seasonsFactory;
@GetMapping("/{code}")
public String strategyTest(@PathVariable("code") Integer code) {
if (code == null) {
return "季节不能为空";
}
SeasonsEnum seasons = SeasonsEnum.getByCode(code);
if (seasons == null) {
return "季节异常";
}
return seasonsFactory.handle(seasons);
}
}
适用场景
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们 的行为,那么使用策略模式可以动态地让一个对象在许多行 为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行 为就只好使用多重的条件选择语句来实现。
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体 策略类中封装算法和相关的数据结构,提高算法的保密性与 安全性。
1、电商网站支付方式,一般分为银联、微信、支付宝,可以采用策略模式
2、电商网站活动方式,一般分为满减送、限时折扣、包邮活动,拼团等可以采用策略模式
注意事项和细节
策略模式的关键是:分析项目中变化部分与不变部分
策略模式的核心思想是:多用组合/聚合少用继承;用行为类组合,而不是行为的继承更有弹性
体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只 要添加一种策略(或者行为)即可,避免了使用多重转移语句(if..else if..else)
提供了可以替换继承关系的办法: 策略模式将算法封装在独立的Strategy类中使得 你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展
需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大
总结
• 在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们 可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为 政策模式。策略模式是一种对象行为型模式。
• 策略模式包含三个角色:环境类在解决某个问题时可以采用多种策略,在环境类中维护一个对抽象策略类的引用实例;抽象策略类为所支持的算法声明了抽象方法,是所有策略类的父类;具体策略类实现了在抽象策略类中定义的算法。
• 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派 给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的 策略类里面,作为一个抽象策略类的子类。
• 策略模式主要优点在于对“开闭原则”的完美支持,在不修改原有系 统的基础上可以更换算法或者增加新的算法,它很好地管理算法族, 提高了代码的复用性,是一种替换继承,避免多重条件转移语句的 实现方式;其缺点在于客户端必须知道所有的策略类,并理解其区别,同时在一定程度上增加了系统中类的个数,可能会存在很多策略类。
• 策略模式适用情况包括:在一个系统里面有许多类,它们之间的区 别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为,一个系统需要动态地在几种算法中选择一种, 避免使用难以维护的多重条件选择语句,希望在具体策略类中封装 算法和与相关的数据结构。