什么是策略模式?一般用在什么场景?
- 标签:设计模式
🏛 业务架构师
策略模式把同一业务动作的多种做法封装成可互换的算法族,运行时按条件选择。结构三件套:策略接口(定义契约)、多个实现(各算法)、上下文/工厂(选择与注入)。
它回答的业务问题是"同一件事有很多种做法,且做法会不断增加"。我用三个真实场景说明:
- 支付渠道路由:Strategy 是"支付",实现是支付宝、微信、银联各一个类。新接一个渠道只加一个实现,主交易流程零改动,回归测试范围可控——支付是公司最核心的链路,"不动主流程"就是最值钱的属性;
- 营销规则引擎:满减、折扣、买赠、组合优惠各是策略,叠加规则引擎配置后,运营可以自助配置活动,把开发资源从"改活动代码"里解放出来;
- 多租户/多站点差异:不同租户的计费、限流策略不同,按租户装配策略即可。
反过来的边界同样重要:如果算法只有一种且看不到扩展预期(比如就一个签名算法),上策略模式纯属过度设计。
我的落地习惯:策略实现用 Spring 容器管理,按类型 Map 注入(Map<String, PayStrategy>),路由逻辑收敛在一个门面里,业务方只面对一个入口。模式的价值最终体现为两个速度:新玩法上线快、老玩法回滚快。
🏗 系统架构师
策略模式把同一行为的不同实现封装成独立策略类,运行时按上下文选择,核心是"用多态替代条件分支"。
结构:Strategy 接口 → 多个实现类(ConcreteStrategyA/B)→ Context 持有策略引用调用。
典型落地(我自己的项目):
- 支付渠道路由:Strategy 接口定义
pay/refund/query,微信、支付宝、银联各一个实现,按渠道码从容器里的 Map 取,新增渠道零侵入; - 营销折扣:满减、折扣、一口价各为策略,价格引擎按规则组合;
- 通知渠道:短信、邮件、Push;
- 数据源路由、重试退避策略。
与工厂的配合:工厂负责"造"策略,策略负责"做"事,常一起出现;配合 Spring 更简洁——所有实现注入 Map<String, Strategy>,key 是 beanName 或自定义注解值,取策略一行代码。
判断该不该用的标准:分支逻辑会持续膨胀、且各分支独立演化时用策略;固定两三种不会再变的分支,直接 if-else 反而清晰——模式是管理变化的工具,不是教条。
💻 全栈开发专家
定义一族算法封装成独立类,运行时按条件替换,替代 if-else/switch 分支膨胀。判断信号:同一段分支逻辑里每个分支只是"做法不同",且未来还会加新做法。
java
public interface PayStrategy {
PayResult pay(Order order);
}
@Component("alipay")
public class AlipayStrategy implements PayStrategy { ... }
@Service
public class PayService {
private final Map<String, PayStrategy> strategyMap; // Spring 注入所有实现
public PayService(List<PayStrategy> list) {
strategyMap = list.stream()
.collect(Collectors.toMap(s -> s.getClass().getAnnotation(Component.class).value(), Function.identity()));
}
public PayResult pay(String channel, Order order) {
return strategyMap.get(channel).pay(order); // 新增渠道零改动
}
}我用过的场景:多渠道支付、优惠计算规则、消息推送(短信/Push/邮件)、导出格式(Excel/CSV)、多租户数据路由。
工程心得:配合 Spring 的 List/Map 注入是最顺手的形式;分支只有两三个且稳定时别硬上策略模式,Map + 函数接口(Map<String, Function<...>>)更轻量。关键收益是新增策略不动老代码(开闭原则),上线时新增类也更好测试。