策略模式核心是将可变算法逻辑抽象为接口,实现隔离、可插拔与运行时切换;适用于多分支无继承、动态切换、多场景不同行为三类业务;接口应聚焦行为契约,策略无状态,上下文仅负责策略执行与异常处理。

用接口实现策略模式,关键不是“写接口”,而是把业务中那些会变的算法逻辑抽出来,让它们彼此隔离、可插拔、运行时可换。生产环境里变量调整频繁(比如优惠规则、风控阈值、路由策略),硬编码 if-else 或配置开关容易失控,而策略模式配合接口,能把“变”和“不变”真正分开。
明确哪些变量属于“可策略化”的业务算法
不是所有变量都适合走策略模式。重点看三类:
- 多分支逻辑强、且分支间无继承关系:例如“按用户等级打不同折扣”“按订单金额走不同运费计算方式”“按地区执行不同税率规则”
- 算法本身会随时间/配置/AB实验动态切换:比如风控模型从规则引擎切到轻量ML模型,或促销从“满300减50”临时切为“满300打9折”
- 同一输入,不同场景需要不同输出行为:如导出报表时,财务线要含税明细,运营线要脱敏聚合,两者字段、格式、权限完全不同
定义策略接口要聚焦“行为契约”,而非数据结构
接口只声明“做什么”,不规定“怎么做”或“用什么数据”。避免把DTO、实体类、配置参数塞进接口方法签名。
✅ 好例子:
public interface PricingStrategy { double calculatePrice(Order order); }
——入参是稳定上下文(Order),返回是确定语义(最终价格)
❌ 避免:
public interface PricingStrategy { double calculatePrice(double base, String couponCode, int userLevel, boolean isVip, Map
——参数膨胀,每次加个新变量就得改接口,所有实现类跟着动
策略加载与切换必须支持运行时生效,不重启
生产环境不能靠重启应用来切算法。推荐两种轻量可控方式:
-
配置中心驱动:在Nacos/Apollo中维护当前生效的策略标识(如
pricing.strategy=premium_v2),监听配置变更,自动替换上下文中的策略实例(注意线程安全与单例复用) -
策略注册表 + 名称查找:启动时扫描所有
@Component的策略实现类,注入Map,运行时通过strategyMap.get(configuredKey)获取,无需反射或 Class.forName
⚠️ 注意:策略对象应是无状态的(stateless)。若有缓存或连接资源,需在初始化时完成,不要在 calculatePrice() 中现场创建连接或读配置。
上下文类要屏蔽策略细节,暴露简洁执行入口
上下文不是策略工厂,也不是调度器。它只做三件事:
- 持有当前策略引用(可设为 volatile 或用 AtomicReference 保证可见性)
- 提供
execute(...)方法,把原始请求参数转成策略所需上下文(如把 HTTP 请求封装为Order对象) - 统一处理策略执行异常(如降级返回默认值、打监控日志、触发告警),不让策略内部错误穿透到上层
示例:
public class PricingContext { private volatile PricingStrategy currentStrategy; public double execute(Order order) { return Optional.ofNullable(currentStrategy) .map(s -> s.calculatePrice(order)) .orElse(order.getBasePrice()); } }
不复杂但容易忽略:变量变的是算法逻辑,不是配置键名;策略模式的价值不在“用了接口”,而在让每一次业务算法调整,变成一次配置更新或一个类的增删,而不是一场代码重构。










