自学教程 学编程从这里开始

策略模式

《策略模式》|设计模式系列第19篇

系列:行为型模式 · 策略模式(Strategy Pattern)
关键词:算法族、封装算法、动态替换算法、解耦算法与调用方

一、什么是策略模式

策略模式(Strategy Pattern):定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。

属于行为型设计模式。

简单理解:
将一组可互换的算法分别封装成独立策略类,全部实现同一个策略接口。上下文持有策略引用,客户端可以在运行时动态替换不同策略。上下文只负责调度,算法实现完全交给策略对象。
例子:排序,可选择 BubbleSort、QuickSort;支付,可选择 Alipay、WechatPay、CreditCardPay。

核心意图
封装算法族,算法独立,可动态替换;算法变化不影响上下文。

适用场景

  1. 有多种算法/策略,需要在运行时动态切换
  2. 消除大量 if/else 或 switch,根据类型选择算法
  3. 算法逻辑经常需要扩展,新增算法不改动原有代码
  4. 算法细节需要隔离,客户端只调用统一接口

⚠️ 缺点预警:策略变多时,类数量增加;客户端需要理解不同策略差异,负责选择策略。

二、UML结构图

角色划分:

  1. Strategy(抽象策略):定义统一算法接口
  2. ConcreteStrategy(具体策略):实现Strategy接口,编写具体算法逻辑
  3. Context(上下文):持有Strategy引用,对外提供方法,委托策略执行算法
  4. Client(客户端):创建策略实例,注入Context,选择使用哪一个策略

三、Java 完整示例

场景:ShoppingCart 购物车,支持不同 discount 策略:NormalDiscount、HolidayDiscount。
代码全部使用英文。

1. Strategy 抽象策略

public interface DiscountStrategy {
    double calculate(double price);
}

2. ConcreteStrategy 具体策略

public class NormalDiscount implements DiscountStrategy {
    @Override
    public double calculate(double price) {
        return price * 0.9;
    }
}

public class HolidayDiscount implements DiscountStrategy {
    @Override
    public double calculate(double price) {
        return price * 0.7;
    }
}

3. Context 上下文

public class PriceContext {
    private DiscountStrategy strategy;

    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public double getFinalPrice(double price) {
        return strategy.calculate(price);
    }
}

4. Client 客户端

public class Client {
    public static void main(String[] args) {
        PriceContext context = new PriceContext();
        double originalPrice = 100;

        context.setStrategy(new NormalDiscount());
        System.out.println("Normal price: " + context.getFinalPrice(originalPrice));

        context.setStrategy(new HolidayDiscount());
        System.out.println("Holiday price: " + context.getFinalPrice(originalPrice));
    }
}

运行输出:

Normal price: 90.0
Holiday price: 70.0

四、策略模式 vs 状态模式

模式目标核心
Strategy客户端主动选择算法,策略之间互相独立无感知算法是可选方案,由外部切换
State对象内部状态驱动行为改变,状态之间可以互相转换状态属于对象内部属性,状态类感知其他状态

五、优缺点总结

✅ 优点

  1. 消除大量条件判断语句
  2. 新增策略只需新增类,符合开闭原则
  3. 算法独立封装,便于单元测试
  4. 运行时动态切换策略

❌ 缺点

  1. 策略多的时候,类数量膨胀
  2. 客户端必须知道各个策略的区别,才能选择合适策略
  3. 简单算法场景,会增加额外代码复杂度

六、框架源码应用

  • JDK java.util.Comparator,Collections.sort 传入不同比较策略
  • Spring ResourceLoader、ConversionService 转换器策略
  • Spring Security AuthenticationProvider

七、小结

策略模式核心:封装一组可互换算法,统一接口,上下文委托执行,客户端动态选择策略。
当业务存在多种可选算法,需要动态切换,优先使用策略模式。

标签:

0 条笔记