Skip to content
快速预览

策略模式(上)--概念

✍️ w 🕒 2023-08-01 14:34:55(10 months ago) 🔗 G.设计模式

策略模式,英文全称是 Strategy Design Pattern。定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。这些策略类可以被互换使用,可以让程序选择不同的算法或者策略来进行具体操作。

策略模式主要解决的问题是在直接的代码级别上实现多种可能的算法或行为,使得代码复杂且难以维护。通过将行为(算法)从其上下文中分离出来,以便能在不改变对象的情况下动态地改变其行为。

为了达到可以将算法抽离出来形成解耦,一般解决方案:

  1. 将每种可能的算法或行为抽象成一个接口或抽象类。每种具体的算法或行为则成为接口或抽象类的一个具体实现。这些具体实现被称为 策略。

  2. 提供一个上下文类,它持有一个策略对象。这个上下文类提供一个设置策略的方法,客户端可以通过这个方法改变上下文的策略。

这么做的好处在于可以在运行时改变对象的行为。这为各种算法或行为提供了高级别的解耦,使得每种算法都可以独立于使用它的客户端而改变或演进,(这里的客户端代指使用算法的代码也就上面的第二条构成部分)。

主要解决问题场景

在讨论主要解决问题场景之前,先看几种业务场景

  1. 替代条件语句:在某些情况下,你可能会发现你的代码中有大量的条件语句。这可能会导致代码变得复杂和难以理解。在这种情况下,你可以使用策略模式将每个条件分支的代码提取到一个单独的类中,这样可以使代码变得更加清晰和易于理解。
  2. 验证策略:例如,你可能有一个需要多种验证方式的系统,包括用户名/密码验证,短信验证,指纹验证,面部识别等。
  3. 负载均衡策略:在一个大型分布式系统中,可能会有多种负载均衡策略,如轮询,随机,按负载选择等。使用策略模式,你可以动态地根据系统状态选择最佳的负载均衡策略
  4. 日志记录策略:在一个系统中,可能有多种日志记录方式,如记录到本地文件,记录到数据库,发送到日志服务等。策略模式可以让你在运行时选择日志记录方式。
  5. 算法策略:当一个问题有多种算法可以解决时,可以使用策略模式来封装每一种算法。这样,你可以在运行时动态选择使用哪一种算法,而不需要改变原有的代码。比如,排序算法(快速排序,冒泡排序等)、压缩和解压缩算法(zip, gzip等)等场景。
  6. 业务规则选择:当一个业务流程在不同的条件下有不同的处理规则时,可以使用策略模式来封装每一种业务规则。这样,可以在运行时根据实际情况选择适合的业务规则进行处理。例如,不同类型的订单使用不同的折扣策略、交通工具根据路况选择不同的行驶策略、支付方式等。
  7. 路线规划:如上面提到的导航应用,可以根据用户的偏好或实时交通情况,选择不同的路线规划策略
  8. 机器学习算法:机器学习有许多不同的算法,比如决策树,支持向量机,神经网络等。策略模式可以让你在运行时选择不同的机器学习算法
  9. 资源调度:在一些需要进行资源调度的系统中,经常需要在多种调度策略中进行选择,如操作系统的进程调度,加载均衡器的请求分配等,都可以使用策略模式来灵活选择最优的策略。

这些场景在一个系统中,存在多种可以互换的算法或行为,都可以使用策略模式来进行设计。

策略模式解决 if else

在使用策略模式的时候最常听说的是 利用策略模式来替换过多的 if-else 嵌套的逻辑判断,举一个具体的例子,假设我们正在编写一个购物应用程序,该应用程序需要计算不同类型的订单的运费。对于每种类型的订单,都有一种不同的运费计算方法。

在没有使用策略模式的情况下,我们可能会在订单类中使用很多if-else语句来处理不同类型的订单。但这样做的问题是,如果我们想添加一种新的订单类型,我们就需要修改订单类,并在其中添加更多的if-else语句。这就使得订单类变得越来越大,越来越难以维护,也违反了开闭原则(对扩展开放,对修改关闭)。

如果使用策略模式,我们可以定义一个计算运费的接口(策略),然后为每种订单类型创建一个实现了该接口的类。订单类只需要引用这个接口,并使用接口中定义的方法来计算运费。当我们需要添加新的订单类型时,我们只需要添加一个新的实现了运费计算接口的类,然后在创建订单时,将这个新的类的实例传给订单类即可。

利用策略模式来替换过多的 if-else 嵌套的逻辑判断 这其实并不是绝对的

虽然策略模式在面对一系列的if-else条件判断时特别有用,因为它可以帮助我们把每个条件对应的逻辑封装成单独的策略类,从而使得代码更易于理解和维护。

然而,策略模式并不是万能的,它并不能解决所有的if-else问题。一般来说,如果以下条件满足,你可以考虑使用策略模式进行重构:

  1. 你的代码中有许多相似的if-else条件判断,这些判断根据不同的条件执行不同的行为。

  2. 这些行为可以被封装为独立的类,每个类对应一个行为

  3. 你需要能在运行时动态地改变对象的行为

虽然策略模式能够处理 许多不同的情况,包括处理复杂的判断逻辑,但是如果你的if-else逻辑比较复杂,条件逻辑非常复杂或者不规则,没有明确的模式可供区分不同的策略,那么策略模式可能就不是最佳选择了

例如,某些条件可能需要访问或者修改其他部分的状态,或者某些条件的处理逻辑可能涉及到多个步骤并且这些步骤之间有一定的依赖关系,那么策略模式可能不是一个好的选择。

因此在决定是否可以使用策略模式来改造复杂的if-else逻辑时,可以考虑以下几个界限:

  1. 行为的差异性:策略模式适用于具有相似但部分不同行为的情况。如果if-else逻辑中的各个分支之间的行为差异性很大,可能需要重新评估是否适合使用策略模式。如果每个分支的行为非常独特,可能需要考虑其他的设计模式或者重构方案。

  2. 条件的数量和复杂性:如果if-else逻辑中有大量的条件和复杂的条件判断逻辑,策略模式可能并不是最佳选择。策略模式适用于将相同类型的条件判断抽象为不同的策略类,而不是用于处理大量复杂的条件逻辑。

  3. 代码的可读性和可维护性:评估if-else逻辑对代码的可读性和可维护性的影响。如果if-else逻辑使得代码难以理解和维护,使用策略模式可以提高代码的可读性。策略模式将各个分支的逻辑封装在单独的策略类中,使得代码更加清晰和易于理解。

  4. 未来的扩展性:如果你预计系统中可能会有新的条件或行为的添加,策略模式可以提供更好的扩展性。通过添加新的策略类,可以轻松地扩展系统的功能,而不需要修改原有的代码。

总之,使用策略模式来改造if-else逻辑需要综合考虑代码的结构、行为差异性、条件的数量和复杂性、代码的可读性和可维护性以及未来的扩展性等因素。根据具体情况来决定是否适合使用策略模式进行重构。

如何使用策略模式

经过上面的分析

当我们需要在程序运行时根据不同的情况选择不同的行为或算法时,策略模式也非常有用。也就是说如果在一个系统里面有许多类,它们之间的区别仅在于它们的'行为',那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。一个系统需要动态地在几种算法中选择一种。

按照这种分析情况,可以将策略模式构成设计拆解三个部分:

  • 抽象策略类(Strategy) :定义策略的共有方法。

  • 具体策略类(StrategyA 等) :实现抽象策略类定义的共有方法。

  • 上下文信息类(Context) :用于存放和执行需要使用的具体策略类以及客户端调用的逻辑。

正是因为这种构成可以让,所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略。示例代码如下所示

按照上面三部分来创建一个策略模式的模型

java
// 找到策略相同的行为创建一个 接口
public interface Strategy {

    void operation();

}

// 策略实现接口的行为
public class StrategyA implements Strategy {

    @Override

    public void operation() {

        System.out.println("=== 执行策略 A ......");

    }

}

// 策略实现接口的行为
public class StrategyB implements Strategy {

    @Override

    public void operation() {

        System.out.println("=== 执行策略 B ......");

    }

}

// 上下文信息类(Context) 进行调用要使用的策略
public class Context {

    public void request(Strategy s) {

        s.operation();

    }

}

// 使用 缩写
new Context().request(new StrategyB())
  • 利用工厂模式创建上下文信息类(Context),我们将策略全部收集,直接调用下面的案例和上面的不同,直接在上下文信息类(Context)创建好策略对象,根据使用的策略条件直接获取要使用的策略对象
java
public class StrategyFactory {
  private static final Map<String, Strategy> strategies = new HashMap<>();

  static {
		//  ConcreteStrategyA  ConcreteStrategyB 作为策略
    strategies.put("A", new ConcreteStrategyA());
    strategies.put("B", new ConcreteStrategyB());
  }

  public static Strategy getStrategy(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }
    return strategies.get(type);
  }
}
  • 上面获取的策略事先创建好每个策略对象,缓存到工厂类中,用的时候直接返回。如果策略类是有状态的,根据业务场景的需要,我们希望每次从工厂方法中,获得的都是新创建的策略对象,而不是缓存好可共享的策略对象,那我们就需要按照如下方式来实现策略工厂类
java
public class StrategyFactory {
  public static Strategy getStrategy(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }

    if (type.equals("A")) {
      return new ConcreteStrategyA();
    } else if (type.equals("B")) {
      return new ConcreteStrategyB();
    }

    return null;
  }
}

使用上面的策略工程上下文

java
// 策略接口:EvictionStrategy
// 策略类:LruEvictionStrategy、FifoEvictionStrategy、LfuEvictionStrategy...
// 策略工厂:EvictionStrategyFactory

public class UserCache {
  private Map<String, User> cacheData = new HashMap<>();
  private EvictionStrategy eviction;

  public UserCache(EvictionStrategy eviction) {
    this.eviction = eviction;
  }

  //...
}

// 运行时动态确定,根据配置文件的配置决定使用哪种策略
public class Application {
  public static void main(String[] args) throws Exception {
    EvictionStrategy evictionStrategy = null;
    Properties props = new Properties();
    props.load(new FileInputStream("./config.properties"));
    String type = props.getProperty("eviction_type");

		// 直接看这里从工厂函数中获取了策略 剩下地方代码可以忽略
    evictionStrategy = EvictionStrategyFactory.getEvictionStrategy(type);
    UserCache userCache = new UserCache(evictionStrategy);
    //...
  }
}

// 非运行时动态确定,在代码中指定使用哪种策略
public class Application {
  public static void main(String[] args) {
    //...
    EvictionStrategy evictionStrategy = new LruEvictionStrategy();
    UserCache userCache = new UserCache(evictionStrategy);
    //...
  }
}

上面代码可以发现策略模式有两种一种是,运行时动态确定 另一种是静态使用直接指定,两种通俗的理解就是,动态是通过在运行时候获取实际状态来来决定使用的策略,静态就是直接在开发阶段就去指定使用策略

java
// 上下文信息类(Context) 进行调用要使用的策略,属于静态
public class Context {

    public void request(Strategy s) {

        s.operation();

    }

}

// 使用 缩写
new Context().request(new StrategyB())

策略模式案例 -- 解决if else

策略模式适用于根据不同类型的动态,决定使用哪种策略这样一种应用场景,这种常见我们写法使用的就是 if-else 或 switch-case 分支判断逻辑,可以通过策略模式优化

java
public class OrderService {
  public double discount(Order order) {
    double discount = 0.0;
    OrderType type = order.getType();
    if (type.equals(OrderType.NORMAL)) { // 普通订单
      //...省略折扣计算算法代码
    } else if (type.equals(OrderType.GROUPON)) { // 团购订单
      //...省略折扣计算算法代码
    } else if (type.equals(OrderType.PROMOTION)) { // 促销订单
      //...省略折扣计算算法代码
    }
    return discount;
  }
}

优化上面代码时候找到 共同的策略点 就是订单类型,将不同类型订单的打折策略设计成策略类,并由工厂类来负责创建策略对象,用 Map 来缓存策略,根据 type 直接从 Map 中获取对应的策略,从而避免 if-else 分支判断逻辑

java
// 策略的定义
public interface DiscountStrategy {
  double calDiscount(Order order);
}
// 省略NormalDiscountStrategy、GrouponDiscountStrategy、PromotionDiscountStrategy类代码...

// 策略的创建
public class DiscountStrategyFactory {
  private static final Map<OrderType, DiscountStrategy> strategies = new HashMap<>();

  static {
    strategies.put(OrderType.NORMAL, new NormalDiscountStrategy());
    strategies.put(OrderType.GROUPON, new GrouponDiscountStrategy());
    strategies.put(OrderType.PROMOTION, new PromotionDiscountStrategy());
  }

  public static DiscountStrategy getDiscountStrategy(OrderType type) {
    return strategies.get(type);
  }
}

// 策略的使用
public class OrderService {
  public double discount(Order order) {
    OrderType type = order.getType();
    DiscountStrategy discountStrategy = DiscountStrategyFactory.getDiscountStrategy(type);
    return discountStrategy.calDiscount(order);
  }
}

如果业务场景需要每次都创建不同的策略对象,这种实现方式相当于把原来的 if-else 分支逻辑,转移到了工厂类中,实际上并没有真正将它移除。和之前相比每个策略变得单一好维护

java
public class DiscountStrategyFactory {
  public static DiscountStrategy getDiscountStrategy(OrderType type) {
    if (type == null) {
      throw new IllegalArgumentException("Type should not be null.");
    }
    if (type.equals(OrderType.NORMAL)) {
      return new NormalDiscountStrategy();
    } else if (type.equals(OrderType.GROUPON)) {
      return new GrouponDiscountStrategy();
    } else if (type.equals(OrderType.PROMOTION)) {
      return new PromotionDiscountStrategy();
    }
    return null;
  }
}

策略模式案例 -- 上下文工厂中if else

上面的案例通过 找到相同点的策略,编写策略模式,但在最后的工厂函数中还是存留了 if else 。现在有个新的需求是实现对一个文件进行排序的功能,提供多种排序方案代码最简单的思路编写,但是下面的代码有问题在设计原则中,函数的行数不能过多,最好不要超过一屏的大小,因此拆成了四个函数,如果代码后续没有扩展这个代码也能运行,但是如果项目后期联动,需要职责单一进行拆分

java
public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;

  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    if (fileSize < 6 * GB) { // [0, 6GB)
      quickSort(filePath);
    } else if (fileSize < 10 * GB) { // [6GB, 10GB)
      externalSort(filePath);
    } else if (fileSize < 100 * GB) { // [10GB, 100GB)
      concurrentExternalSort(filePath);
    } else { // [100GB, ~)
      mapreduceSort(filePath);
    }
  }

  private void quickSort(String filePath) {
    // 快速排序
  }

  private void externalSort(String filePath) {
    // 外部排序
  }

  private void concurrentExternalSort(String filePath) {
    // 多线程外部排序
  }

  private void mapreduceSort(String filePath) {
    // 利用MapReduce多机排序
  }
}

public class SortingTool {
  public static void main(String[] args) {
    Sorter sorter = new Sorter();
    sorter.sortFile(args[0]);
  }
}

使用策略模式进行重构后,将算法进行抽离形成类

java
public interface ISortAlg {
  void sort(String filePath);
}

public class QuickSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}

public class ExternalSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}

public class ConcurrentExternalSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}

public class MapReduceSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}

// 创建上下文收集的策略的 工厂函数
public class SortAlgFactory {
  private static final Map<String, ISortAlg> algs = new HashMap<>();

  static {
    algs.put("QuickSort", new QuickSort());
    algs.put("ExternalSort", new ExternalSort());
    algs.put("ConcurrentExternalSort", new ConcurrentExternalSort());
    algs.put("MapReduceSort", new MapReduceSort());
  }

  public static ISortAlg getSortAlg(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }
    return algs.get(type);
  }
}

public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;

  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    ISortAlg sortAlg;

		// 使用
    if (fileSize < 6 * GB) { // [0, 6GB)
      sortAlg = SortAlgFactory.getSortAlg("QuickSort");
    } else if (fileSize < 10 * GB) { // [6GB, 10GB)
      sortAlg = SortAlgFactory.getSortAlg("ExternalSort");
    } else if (fileSize < 100 * GB) { // [10GB, 100GB)
      sortAlg = SortAlgFactory.getSortAlg("ConcurrentExternalSort");
    } else { // [100GB, ~)
      sortAlg = SortAlgFactory.getSortAlg("MapReduceSort");
    }
    sortAlg.sort(filePath);
  }
}

现在的最终代码还是和第一个案例没有区别收集上下文的工厂函数还是依旧有这 if else,我们需要一个类的职责是将一个排序算法和一个文件大小范围绑定在一起,依次循环找到最终要执行的,思路有了开始代码实现。

依旧还是将每一种的排序方法形式进行了策略类的定义,不同是 通过遍历AlgRange列表并检查文件大小是否在AlgRange的范围内来实现的。一旦找到合适的AlgRange,就会使用其对应的排序算法对文件进行排序。AlgRange类的职责是将一个排序算法和一个文件大小范围绑定在一起,可以通过一个数组的 表 对我们条件和映射形成收集

java
private static class AlgRange {
    private long start;
    private long end;
    private ISortAlg alg;

    public AlgRange(long start, long end, ISortAlg alg) {
      this.start = start;
      this.end = end;
      this.alg = alg;
    }

    public ISortAlg getAlg() {
      return alg;
    }

    public boolean inRange(long size) {
      return size >= start && size < end;
    }
  }
}

public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;
  private static final List<AlgRange> algs = new ArrayList<>();
  static {
    algs.add(new AlgRange(0, 6*GB, SortAlgFactory.getSortAlg("QuickSort")));
    algs.add(new AlgRange(6*GB, 10*GB, SortAlgFactory.getSortAlg("ExternalSort")));
    algs.add(new AlgRange(10*GB, 100*GB, SortAlgFactory.getSortAlg("ConcurrentExternalSort")));
    algs.add(new AlgRange(100*GB, Long.MAX_VALUE, SortAlgFactory.getSortAlg("MapReduceSort")));
  }

  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    ISortAlg sortAlg = null;
    for (AlgRange algRange : algs) {
      if (algRange.inRange(fileSize)) {
        sortAlg = algRange.getAlg();
        break;
      }
    }
    sortAlg.sort(filePath);
  }

策略模式的好处

  1. 提升代码的可维护性:通过使用策略模式,可以将不同的算法封装在不同的类中,使得代码结构更加清晰,易于维护。

  2. 动态快速替换算法:策略模式将使用算法的逻辑和算法实现的逻辑分离,使得在需要替换算法时更加方便,可以快速采用最新的算法实现。

  3. 应对频繁更换策略的场景:对于需要频繁更换策略的场景,如用户推荐类场景,对于一些 C 端产品来说,在获取了用户的反馈数据后,会根据用户的特性制定不同的运营策略,这时如果采用 if-else 的方式编码,那么每一次的策略变化都会导致系统代码的修改,从运营的角度看是不可接受的,而采用策略模式就能很容易地解决这个问题。

  4. 策略模式在编程中提供了良好的代码扩展性,可以根据需要生成新的具体策略类,满足开闭原则和里氏替换原则。这样用户可以在不修改原有系统的基础上选择算法或行为,同时也可以灵活地增加新的算法或行为。

  5. 能够降低使用多重条件(if-else)嵌套语句的理解难度

策略模式的问题

策略模式在一些情况下可能会增加客户端的学习成本,因为客户端需要了解所有的策略才能做出选择。同时,策略模式也会增加维护成本,因为每个具体策略都对应一个策略类,当策略较多时,需要维护的类数量也会增加。相比之下,函数式编程使用策略模式可能更简洁,特别是对于一些小型的策略来说,使用函数式编程可以更方便地实现不同版本的算法。

总结

一个完整的策略模式就是由这三个部分组成的。

  • 策略类的定义比较简单,包含一个策略接口和一组实现这个接口的策略类。
  • 策略的创建由工厂类来完成,封装策略创建的细节。
  • 策略模式包含一组策略可选,客户端代码如何选择使用哪个策略,有两种确定方法:编译时静态确定和运行时动态确定。其中,“运行时动态确定”才是策略模式最典型的应用场景。

策略模式适用于许多不同的情况,包括处理复杂的判断逻辑。但是,如果你的条件逻辑非常复杂或者不规则,没有明确的模式可供区分不同的策略,那么策略模式可能就不是最佳选择了。

在使用策略模式时,重要的是每个策略应当能清晰、准确地定义其应用条件。这样,当应用程序在运行时需要确定采取何种策略时,可以根据这些定义的条件进行有效的决策。

尽管策略模式有这些优点,但并不意味着应该在所有情况下都使用策略模式。如果你的条件逻辑非常复杂或者不规则,没有明确的模式可供区分不同的策略,那么策略模式可能就不是最佳选择了,你可能需要考虑其他设计模式或者更灵活的逻辑结构

最重要的是,任何设计模式(包括策略模式)都不应被强制应用于所有情况。你应该根据你的具体需求和上下文来选择最合适的设计模式。每个设计模式都有其优势和适用情况,理解这些能帮助你做出更好的设计决策。

最终,是否使用策略模式(或者其他设计模式)并没有一个硬性的规定,这主要取决于你的具体需求以及你对这些设计模式的理解。在实践中,理解并运用设计模式需要一定的经验,而且应当遵循"优先考虑简洁性和可读性"的原则。设计模式的目的是提高代码的可维护性和可复用性,如果过度使用或者不适当的使用设计模式反而会使代码变得更加复杂和难以理解。

不要陷入的误区

业务复杂达到一定程度了我们才选用设计模式去解决复杂的问题,扩展性 复用性,冗余度,小的情况没必要使用在这种情况下

个人心得

  1. 并不是所有的 if else 都能够做 策略模式,如果判断条件过于复杂切没有相同使用规律 和 只是简单的判断 是没必要做测试模式的
  2. 策略模式重要的是找到 是做同一件事情的不同方法,这些方法不能重复 他们的交集,例如 登录形式二维码还是密码他们行为都是登录,例如支付方式支付宝还是微信他们的行为都是支付,找到共同点进行策略的抽离,可能大量的条件中就一个能做到抽离
js
// 伪代码 判断状态和大小
if(type == "size" && size > 100){

}else if(type == "length" && size > 500) {

}
.....
// 可以按照 抽离 type 这种简单的共同点切入
{
	size(){},
	length(){},
}

if( size > 100){
  size(){},
}else if(& size > 500) {
	length(){},
}
// 当然也可以像上面的案例 利用数组收集各个条件
  1. 代码复杂性:如果你的代码中有大量的 if-else 或 switch-case 语句,这可能会使代码变得非常复杂,难以阅读和维护。在这种情况下,使用策略模式可以帮助简化代码,使其更易于理解和维护。

  2. 开闭原则:如果你的代码需要经常添加新的条件分支,这可能会违反开闭原则(软件实体应该对扩展开放,对修改关闭)。在这种情况下,使用策略模式可以使你的代码更易于扩展,因为你可以添加新的策略而不需要修改现有的代码。

  3. 代码重用:如果你的代码中有很多重复的 if-else 或 switch-case 语句,这可能会导致代码重复。在这种情况下,使用策略模式可以帮助减少代码重复,因为你可以将共享的逻辑抽取到一个策略中。

  4. 单一职责原则:如果你的代码中的一个类或方法有太多的职责,这可能会违反单一职责原则(一个类或方法应该只有一个改变的原因)。在这种情况下,使用策略模式可以帮助你将这些职责分解到不同的策略中,使每个策略都只有一个职责。

  5. 需要动态更改行为:如果你的代码需要在运行时动态地更改其行为,使用策略模式可以使这种更改更加容易,因为你可以在运行时更换策略

Released under the MIT License.