策略模式

129 阅读2分钟

策略模式

先看概念🙌

官方定义:策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在策略模式中,我们定义了一组算法,并且允许客户端应用程序在运行时选择要使用的实际算法。

说人话:挺好理解的,就是就是使用不同的策略算法不会影响到客户端的使用

适用场景😶‍🌫️

策略模式还是比较简单并且使用较多的,平常我们多运用策略模式用来消除 if-else、switch 等多重判断的代码,消除 if-else、switch 多重判断 可以有效应对代码的复杂性。

直接上demo

假设有一个根据不同商品类型计算折扣的问题。在没有使用策略模式的情况下,你可能会写出类似下面的代码:

  public class DiscountCalculator {
      public double calculateDiscount(String productType, double amount) {
          if ("electronics".equals(productType)) {
              return amount * 0.1;
          } else if ("clothing".equals(productType)) {
              return amount * 0.2;
          } else if ("books".equals(productType)) {
              return amount * 0.15;
          } else {
              return 0;
          }
      }
      public static void main(String[] args) {
          DiscountCalculator calculator = new DiscountCalculator();
          double discount = calculator.calculateDiscount("electronics", 100);
          System.out.println("Discount: " + discount);
      }
  }

我想将上述代码块改造为策略设计模式,怎么办?

别急🙌🙌🙌

先进行一层抽象!!!

把策略定义为一个抽象接口,然后写它的几个实现类,,最后写一个策略类来存储那几个实现类,对客户端屏蔽具体的创建细节

image.png

接下来,就是使用了,看看客户端怎么使用?

image.png

很简单,直接从策略工厂中选一个,然后执行具体的策略

没了?😂确实没了,话说各种设计模式只是一种思想,理解了最重要的是怎么想着在代码中使用到👌

公司中的实践

策略类的设计

首先定义策略类接口:

 /**
  * 商机库权限校验策略类
  */
 public interface BusinessAuthStrategy extends InitializingBean 

继承Spring中的InitializingBean是为了在重写afterPropertiesSet

重写是为了在Spring容器完成对当前bean的属性注入后,将这个bean注册到BusinessAuthFactory的策略工厂中

然后定义抽象策略类:

 /**
  * 商机库权限校验策略类
  */
 public abstract class BusinessAbstractAuthStrategy implements BusinessAuthStrategy

然后其中一个具体策略实现:

 /**
  * 商机库地区&业态权限校验
  */
 @Slf4j
 @Service
 @Component("businessAreaAuthStrategy")
 public class BusinessAreaAuthStrategy extends BusinessAbstractAuthStrategy

策略工厂的设计

策略工厂中使用ConcurrentHashMap来保存每个策略

 /**
  * 商机库权限校验策略类工厂
  *
  * @author sjz
  */
 @Slf4j
 public class BusinessAuthFactory {
     static Map<BusinessAuthEnum, BusinessAuthStrategy> businessLibraryQuotaStrategyHashMap = new ConcurrentHashMap<>();
 ​
     private BusinessAuthFactory() {
     }
 ​
     public static void registryInstance(BusinessAuthEnum key, BusinessAuthStrategy service) {
         if (!businessLibraryQuotaStrategyHashMap.containsKey(key)) {
             businessLibraryQuotaStrategyHashMap.put(key, service);
         }
     }
 ​
     public static BusinessAuthStrategy getInstance(BusinessAuthEnum key) {
         return businessLibraryQuotaStrategyHashMap.get(key);
     }
 }

使用

直接使用策略工厂的静态方法完成校验

 BusinessAuthFactory.getInstance(BusinessAuthEnum.CUSTOM_MONITORING

OK再见!周末快乐!