落地动态策略模式的关键是将if-else替换为可运行时切换的策略对象,优先处理频繁变更、多场景并存、需灰度或ab测试的逻辑,策略接口轻量、实现专注、依赖注入、配置驱动热更新,并配套元信息、降级、监控等能力。

直接把 if-else 拆掉,换成可运行时切换的策略对象,是落地动态策略模式最实在的一步。关键不在“多写几个类”,而在于让业务规则真正变成能装、能换、能查、能灰度的组件。
明确哪些逻辑该抽成策略
不是所有分支都适合策略化。优先处理三类:频繁变更(如优惠计算方式每月一调)、多场景并存(如不同城市用不同风控阈值)、需灰度或AB测试(如新老路由算法共存)。硬编码里反复出现的 switch(code) 或 if(type.equals("A")) 就是信号。
- 把判断条件(比如用户等级、订单金额区间、地域编码)从策略内部移出,由上下文统一传入
- 每个策略只专注“怎么做”,不关心“什么时候用”——后者交给规则引擎或配置中心
- 避免策略间互相调用,保持无状态;若有共享计算,抽成独立服务而非策略成员
接口定义要轻,实现要专
策略接口不是功能大全,而是最小行为契约。例如优惠策略,接口只需 define calculateDiscount(Order order): BigDecimal;而不是塞进日志、缓存、幂等校验等横切逻辑。
- 接口方法参数尽量用领域对象(如 Order、RiskContext),别传一堆零散字段
- 具体策略类命名体现业务语义,如 SummerPromotionStrategy、VipTier2DiscountStrategy,便于排查和配置
- 策略类本身不持有 Spring Bean 引用,需依赖的服务通过构造器注入,保证可测试性
运行时加载与切换机制
策略不能靠重启加载。生产环境常用两种方式结合:配置驱动 + 类加载隔离。
- 用配置中心(如 Apollo/Nacos)管理当前生效的策略 ID,上下文类监听变更并刷新策略实例
- 对需热更新的策略(如临时活动规则),用自定义 ClassLoader 加载 jar 包,配合接口抽象屏蔽类路径差异
- 加一层策略工厂,支持按 key 获取、按标签筛选、按权重路由,为灰度发布留出扩展点
配套能力不可少
光有策略类不够,得让整个链路“活”起来。
- 每个策略实现提供 selfDescribe() 方法,返回版本、作者、适用条件等元信息,供运维界面展示
- 执行入口统一包装 try-catch + 耗时打点,失败时自动降级到默认策略,并告警
- 配合 AOP,在策略执行前后记录 traceId 和输入输出,方便问题回溯











