【设计模式】策略模式(Strategy)详解:把 if-else 变成可切换的算法
文章目录
1. 引言:if-else 正在失控
在实际项目中,你很可能见过这样的代码:
publicdoublecalculate(double price,String type){if("VIP".equals(type)){return price *0.8;}elseif("SVIP".equals(type)){return price *0.6;}elseif("NORMAL".equals(type)){return price;}return price;}问题非常明显:
- if-else 越来越长
- 新规则要改老代码
- 违反开闭原则
当条件分支开始膨胀时,策略模式就是最优解。有选择,就有策略。
2. 什么是策略模式
GoF 定义
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
详解:策略模式模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
一句话理解:
把算法当成对象来用。
3. 策略模式的核心思想
策略模式的本质是:
- 行为抽象
- 算法解耦
- 运行期切换
它强调:
用组合代替条件判断。
4. 策略模式的结构
策略模式包含三个角色:
- Strategy(策略接口)类
这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- ConcreteStrategy(具体策略)类
实现了抽象策略定义的接口,提供具体的算法实现或行为。
- Context(上下文)
持有一个策略类的引用,最终给客户端调用。
5. 示例:商品价格计算
5.1 策略接口
publicinterfacePriceStrategy{doublecalculate(double price);}5.2 具体策略
publicclassNormalPriceStrategyimplementsPriceStrategy{publicdoublecalculate(double price){return price;}}publicclassVipPriceStrategyimplementsPriceStrategy{publicdoublecalculate(double price){return price *0.8;}}publicclassSvipPriceStrategyimplementsPriceStrategy{publicdoublecalculate(double price){return price *0.6;}}5.3 上下文
publicclassPriceContext{privatePriceStrategy strategy;publicPriceContext(PriceStrategy strategy){this.strategy = strategy;}publicdoublegetFinalPrice(double price){return strategy.calculate(price);}}5.4 客户端使用
PriceContext context =newPriceContext(newVipPriceStrategy());System.out.println(context.getFinalPrice(100));运行时随意切换算法。
6. 策略模式的优点
- 消除 if-else
- 算法可自由扩展
- 符合开闭原则
- 运行期灵活切换
7. 策略模式的缺点
- 类数量增加
- 客户端需理解策略
- 策略选择逻辑需额外管理
8. 策略 vs 模板方法
| 维度 | 策略模式 | 模板方法 |
|---|---|---|
| 技术手段 | 组合 | 继承 |
| 切换方式 | 运行期 | 编译期 |
| 灵活性 | 高 | 中 |
9. JDK 中的策略模式
Comparator
Collections.sort(list, comparator);排序算法不变,比较规则可切换。
10. 适用场景
- 规则引擎
- 支付策略
- 排序算法
- 风控策略
11. 一个常见误区
策略模式不是为了“多写类”,而是为了“少写条件判断”。