Skip to content

什么是策略模式?一般用在什么场景? ​

  • 标签:设计模式

🏛 业务架构师 ​

策略模式把同一业务动作的多种做法封装成可互换的算法族,运行时按条件选择。结构三件套:策略接口(定义契约)、多个实现(各算法)、上下文/工厂(选择与注入)。

它回答的业务问题是"同一件事有很多种做法,且做法会不断增加"。我用三个真实场景说明:

  • 支付渠道路由: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<...>>)更轻量。关键收益是新增策略不动老代码(开闭原则),上线时新增类也更好测试。