策略模式核心是解耦条件逻辑与主流程,通过统一接口、独立策略类、集中选取机制(如map或注解扫描)及上下文协调实现可插拔、可测试、可复用。

策略模式不是为了“消灭if-else”而存在,而是把散落在方法体里的条件判断逻辑,从主流程中剥离出来,变成可插拔、可测试、可复用的对象。真正优雅的地方在于:业务代码不再关心“该走哪条分支”,只负责“选哪个策略”。
明确策略边界,先定义统一接口
所有需要被替代的 if 分支,必须解决同一类问题(比如“计算折扣”“处理订单类型”“解析消息格式”),且输入输出结构一致。这时定义一个清晰的策略接口:
- 接口方法名要体现行为意图,如 calculate()、handle(OrderDTO)、parse(String raw)
- 参数尽量精简,避免把整个上下文对象传入;必要时可封装为专用入参对象
- 返回值类型统一,便于后续组合或链式调用
每个分支对应一个具体策略类
原来 if 中的一段逻辑,现在就是一个独立类。它不依赖其他策略,也不感知调用方:
- 例如 VIP 折扣写成 VipDiscountStrategy,黄金会员写成 GoldDiscountStrategy
- 策略类里只放纯业务规则,不包含日志、事务、远程调用等横切逻辑(这些应由上下文或 AOP 处理)
- 避免在策略内部做 null 判断或异常兜底——那是 Context 或调用方的责任
用工厂或注册表解耦策略选择逻辑
原来 if-else 的判断部分,现在转交给策略选取机制。常见做法有两种:
- Map 查表法:启动时将策略按 key(如用户等级字符串)注册进 ConcurrentHashMap,运行时直接 get(key)
- 注解 + Spring 扫描:给策略类加自定义注解(如 @OrderType("PROMOTION")),通过 ApplicationContext 获取所有带该注解的 Bean,构建映射关系
关键点是:这个“选策略”的动作本身,应该集中、可配置、易替换,而不是分散在各处 new 实例。
上下文类承担协调职责,不参与规则决策
Context 是策略的使用者,不是规则制定者:
- 它持有策略引用(通常通过构造器或 setter 注入)
- 它把原始参数转换成策略所需格式,再委托执行
- 它可封装通用前置校验、后置日志、异常包装等,但绝不写 if 来决定用哪个策略
比如一个 OrderService,它只做“根据订单类型获取对应策略 → 执行 handle() → 返回结果”,不出现任何 type.equals("xxx")。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











