策略模式结合工厂模式是解决“同一行为、多种实现、动态切换”的最优组合方案,通过接口定义行为、实现类专注逻辑、工厂自动匹配策略,支持注解或spi自动化注册,重构后新增策略无需修改旧代码。

策略模式结合工厂模式,是解决“同一行为、多种实现、动态切换”这类复杂业务逻辑最实用的组合方案。它不靠堆砌 if-else,而是用结构化方式把变化点隔离出来,让新增逻辑只需加类、不改旧代码。
核心思路:用工厂管策略,用策略管逻辑
策略模式负责定义“能做什么”(接口)和“具体怎么做”(实现类),工厂模式则负责“该用哪一个”(按类型自动匹配并返回)。两者结合后,调用方只关心“我要什么类型”,完全不用知道背后是哪个类在干活。
- 策略接口统一方法签名,比如 execute(String type, Object data)
- 每个具体策略类专注一种场景,例如 RedPacketRewardStrategy 只处理红包发放
- 工厂类内部用 Map
缓存所有已注册策略,启动时自动扫描加载 - 客户端直接 factory.get("RED_PACKET").execute(...),零判断、零耦合
如何避免手动注册几十个策略?
当策略类达到十几甚至上百个时,硬编码注入或逐个 put 到 Map 会非常反人类。推荐两种轻量级自动化方案:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 用自定义注解(如 @RewardStrategy("COUPON"))标记每个策略类,配合 Spring 的 ApplicationContextAware 在启动时扫描所有带该注解的 Bean 并注册进工厂
- 不依赖 Spring 的项目,可用 ServiceLoader 或 Java SPI 机制,把策略实现类全名写进 META-INF/services/xxx.Strategy 文件,运行时自动加载
实际业务中怎么落地?以订单优惠计算为例
原始代码里一堆嵌套 if 判断 orderType、userLevel、isVip、时间区间……维护起来像在拆炸弹。重构后:
- 定义 DiscountStrategy 接口,含 calculate(BigDecimal original, Map
context) - 写 NewUserDiscountStrategy、SeckillDiscountStrategy、VipNightDiscountStrategy 等具体类,各自实现独立逻辑
- 工厂根据订单中的 discountCode 或 sceneId 查出对应策略,一行代码完成计算:strategy.calculate(amount, params)
- 后续加新优惠类型?新建一个策略类 + 加个注解,其他地方一动不动
要不要加 Context 封装层?
如果策略调用较频繁、参数固定(比如总要传 userId、tenantId、traceId),可以加一层轻量 StrategyContext:
- 它不新增逻辑,只做透传和兜底,比如统一记录执行耗时、捕获未注册类型的异常并抛友好提示
- 避免每个 Controller 都重复写 factory.get(xxx) + null 判断 + try-catch
- 不是必须项,小项目可省;中大型系统建议加上,提升调用一致性和可观测性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










