1. 介绍

在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。

  • 要点1:必须将 if else 的代码,封装到不同的策略类中。

  • 要点2:将选择哪种策略的逻辑给放到一个工厂类中去,选择策略的代码务必很简洁。

  • 要点3:context可有可无,具体看策略执行。如果只要一行代码调用,则不需要context。如果策略执行逻辑较复杂,可以用context来封装执行逻辑。

设计模式的重点是思想,大部分业务场景不会只有一种设计模式,很多情况都是多种设计模式相结合。例如策略模式,往往需要结合工厂模式来使用。

1.1 应用实例

  • 支付方式选择: 支付宝、微信支付、银行卡等策略动态切换。

  • 游戏角色技能: 不同武器对应不同的攻击策略。

  • 数据压缩/加密: 支持多种压缩算法(ZIP、RAR)或加密方式(AES、DES)。

  • 优惠券计价: 计算价格时,不同优惠券计价逻辑不同。

1.2 优缺点及建议

  • 优点

    • 避免多重条件语句,代码更清晰。

    • 易于扩展新算法(开闭原则)。

    • 算法可复用和单元测试。

  • 缺点

    • 客户端需了解所有策略类(需权衡)。可以配合工厂模式来避免。

    • 策略类数量可能增多(需合理设计)。

  • 使用建议

    • 当系统中有多种算法或行为,且它们之间可以相互替换时,使用策略模式。

    • 当系统需要动态选择算法时,策略模式是一个合适的选择。

  • 注意事项

    • 如果系统中策略类数量过多,考虑使用其他模式或设计技巧来解决类膨胀问题。

2. 实现及相关代码

假设某业务需要优惠券计价,根据类型不同,选择不同优惠券进行计价。

2.1 没使用设计模式方式

2.1.1 调用方法
    public static void main(String[] args) {
        // 优惠券类型
        int discountStyle = 1;
        if(discountStyle == 1) {
            System.out.println("执行优惠计价方式1的复杂业务逻辑");
        } else if(discountStyle == 2) {
            System.out.println("执行优惠计价方式2的复杂业务逻辑");
        } else if(discountStyle == 3) {
            System.out.println("执行优惠计价方式3的复杂业务逻辑");
        } else {
            System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
        }
    }
    2.1.2 可能会遇到的问题

    在实际的业务代码中,常见的结构是上面这样的,但是每个if和if else之间的代码行数,可能多达几十行,甚至几百行。造成整个计价方法会很庞大。

    若干年后如果要调整逻辑或者修改 bug,需要整体阅读一下代码,阅读大量if else及代码块内的逻辑,调整起来很麻烦。

    2.2 使用设计模式方式

    使用策略模式,可以使逻辑清晰,将if else中的逻辑封装到一个个策略中,集中管理,方便阅读及调整;也会简化整体方法及if else。

    2.2.1 接口及数据对象
      public interface DiscountCalculateStrategy {
          void calculate();
      }
      
      public static class DiscountCalculateStrategyA implements DiscountCalculateStrategy {
          public void calculate() {
              System.out.println("执行优惠计价方式1的复杂业务逻辑");
          }
      }
      
      public static class DiscountCalculateStrategyB implements DiscountCalculateStrategy {
          public void calculate() {
              System.out.println("执行优惠计价方式2的复杂业务逻辑");
          }
      }
      
      public static class DiscountCalculateStrategyC implements DiscountCalculateStrategy {
          public void calculate() {
              System.out.println("执行优惠计价方式3的复杂业务逻辑");
          }
      }
      
      public static class DiscountCalculateStrategyDefault implements DiscountCalculateStrategy {
          public void calculate() {
              System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
          }
      }
      
      /** 获取计价策略的核心工厂 */
      public static class DiscountCalculateStrategyFactory {
          public static DiscountCalculateStrategy getDiscountCalculateStrategy(int discountStyle) {
              if(discountStyle == 1) {
                  return new DiscountCalculateStrategyA();
              } else if(discountStyle == 2) {
                  return new DiscountCalculateStrategyB();
              } else if(discountStyle == 3) {
                  return new DiscountCalculateStrategyC();
              } else {
                  return new DiscountCalculateStrategyDefault();
              }
          }
      }
      
      public static class Context {
          private DiscountCalculateStrategy strategy;
      
          public DiscountCalculateStrategy getStrategy() {
              return strategy;
          }
      
          public void setStrategy(DiscountCalculateStrategy strategy) {
              this.strategy = strategy;
          }
      
          public void calculate() {
              strategy.calculate();
          }
      }
      2.2.2 调用方法
        public static void main(String[] args) {
            // 优惠券类型
            int discountStyle = 1;
            // 配合工厂模式,屏蔽大量 if else
            DiscountCalculateStrategy strategy = DiscountCalculateStrategryFactory
                    .getDiscountCalculateStrategy(discountStyle);
            // 执行对应的计价策略
            Context context = new Context();
            context.setStrategy(strategy);
            context.calculate();
        }

        更多推荐