《策略模式》|设计模式系列第19篇
系列:行为型模式 · 策略模式(Strategy Pattern)
关键词:算法族、封装算法、动态替换算法、解耦算法与调用方
一、什么是策略模式
策略模式(Strategy Pattern):定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。
属于行为型设计模式。

简单理解:
将一组可互换的算法分别封装成独立策略类,全部实现同一个策略接口。上下文持有策略引用,客户端可以在运行时动态替换不同策略。上下文只负责调度,算法实现完全交给策略对象。
例子:排序,可选择 BubbleSort、QuickSort;支付,可选择 Alipay、WechatPay、CreditCardPay。
核心意图
封装算法族,算法独立,可动态替换;算法变化不影响上下文。
适用场景
- 有多种算法/策略,需要在运行时动态切换
- 消除大量 if/else 或 switch,根据类型选择算法
- 算法逻辑经常需要扩展,新增算法不改动原有代码
- 算法细节需要隔离,客户端只调用统一接口
⚠️ 缺点预警:策略变多时,类数量增加;客户端需要理解不同策略差异,负责选择策略。
二、UML结构图
角色划分:
- Strategy(抽象策略):定义统一算法接口
- ConcreteStrategy(具体策略):实现Strategy接口,编写具体算法逻辑
- Context(上下文):持有Strategy引用,对外提供方法,委托策略执行算法
- Client(客户端):创建策略实例,注入Context,选择使用哪一个策略

三、Java 完整示例
场景:ShoppingCart 购物车,支持不同 discount 策略:NormalDiscount、HolidayDiscount。
代码全部使用英文。
1. Strategy 抽象策略
public interface DiscountStrategy {
double calculate(double price);
}
2. ConcreteStrategy 具体策略
public class NormalDiscount implements DiscountStrategy {
@Override
public double calculate(double price) {
return price * 0.9;
}
}
public class HolidayDiscount implements DiscountStrategy {
@Override
public double calculate(double price) {
return price * 0.7;
}
}
3. Context 上下文
public class PriceContext {
private DiscountStrategy strategy;
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double getFinalPrice(double price) {
return strategy.calculate(price);
}
}
4. Client 客户端
public class Client {
public static void main(String[] args) {
PriceContext context = new PriceContext();
double originalPrice = 100;
context.setStrategy(new NormalDiscount());
System.out.println("Normal price: " + context.getFinalPrice(originalPrice));
context.setStrategy(new HolidayDiscount());
System.out.println("Holiday price: " + context.getFinalPrice(originalPrice));
}
}
运行输出:
Normal price: 90.0
Holiday price: 70.0
四、策略模式 vs 状态模式
| 模式 | 目标 | 核心 |
|---|---|---|
| Strategy | 客户端主动选择算法,策略之间互相独立无感知 | 算法是可选方案,由外部切换 |
| State | 对象内部状态驱动行为改变,状态之间可以互相转换 | 状态属于对象内部属性,状态类感知其他状态 |
五、优缺点总结
✅ 优点
- 消除大量条件判断语句
- 新增策略只需新增类,符合开闭原则
- 算法独立封装,便于单元测试
- 运行时动态切换策略
❌ 缺点
- 策略多的时候,类数量膨胀
- 客户端必须知道各个策略的区别,才能选择合适策略
- 简单算法场景,会增加额外代码复杂度
六、框架源码应用
- JDK
java.util.Comparator,Collections.sort 传入不同比较策略 - Spring ResourceLoader、ConversionService 转换器策略
- Spring Security AuthenticationProvider
七、小结
策略模式核心:封装一组可互换算法,统一接口,上下文委托执行,客户端动态选择策略。
当业务存在多种可选算法,需要动态切换,优先使用策略模式。
0 条笔记