• 策略模式


    背景

      之前接的一个需求,在创建店铺页面,根据用户的选择来判断到底是创建新系统店铺还是旧系统的店铺。一般情况下,都是根据前端传入的参数进行if else判断。但既然都是Senior Java Developer了,那就玩点花活吧,于是决定使用策略模型来实现。

    实现

      策略模式,大白话来说,就是不同的场景下使用不同的策略来完成任务。在我这个场景中,需要根据前端传入的不同参数来实现不同的开店策略。先定义一个开店策略,具体的逻辑由实现类实现,如下:

              /**
               * @author Reece
               * @Description 策略接口
               */
              public interface CreateShopStrategy {
    
    
                /*
                 * 创建店铺
                 * @param reqVO
                 * @return com.example.demos.model.ShopVO
                 * @author Reece
                 * @date 2022/4/10 20:14:02
                 */
                ShopVO createShop(CreateShopReqVO reqVO);
    
    
                /*
                 * 具体的策略类型
                 * @param
                 * @return java.lang.Integer
                 * @author Reece
                 */
                Integer getType();
              }
    

    然后就是策略集合,到底有多少种策略,使用枚举就可以了。

              /**
               * @author Reece
               * @Description 策略集合
               */
              @Getter
              public enum StrategyType {
    
                OLD(1,"旧系统"),
                NEW(2,"新系统");
    
    
                private final Integer type;
    
    
                private final String desc;
    
    
                StrategyType(Integer type, String desc) {
                  this.type = type;
                  this.desc = desc;
                }
              }
    

      接下来就是具体的子类实现类了。

                /**
                 * @author Reece
                 * @Description 旧系统的开店逻辑
                 */
                @Service
                public class OldCreateShopImpl extends CreateShopStrategy {
    
    
    
                  @Override
                  public ShopVO createShop(CreateShopReqVO reqVO) {
                    return ShopVO.builder().shopName("OldCreateShopImpl").uid(reqVO.getUid()).id(new Random().nextLong()).build();
                  }
    
    
                  @Override
                  public Integer getType() {
                    return StrategyType.OLD.getType();
                  }
    
                }
    
    
                /**
                 * @author Reece
                 * @Description 新系统的开店逻辑
                 */
                @Service
                public class NewCreateShopImpl extends CreateShopStrategy {
    
    
                  @Override
                  protected ShopVO createShop(CreateShopReqVO reqVO) {
                    return ShopVO.builder().shopName("NewCreateShopImpl").uid(reqVO.getUid()).id(new Random().nextLong()).build();
                  }
    
                  @Override
                  protected Integer getType() {
                    return StrategyType.NEW.getType();
                  }
    
                }
    

    好了,实现类都有了,策略模式的开发完成了。但是现在又有新的问题,前端传入了type,难道还使用if(type==?)来判断?策略模式没有之前,我用if else来判断。策略模式有了,我还是用if else来判断。那策略模式不就白写了么? 淡定,淡定,接下来就是工厂模式该出场的时候了。

    所谓工厂模式即是在创建对象时对客户端屏蔽具体的创建逻辑,只通过接口来返回所需的具体对象。这里我们利用Spring容器的自动注入来方便快捷地实现工厂模式。

              /**
               * @author Reece
               * @Description
               */
              @Component
              public class CreateShopStrategyFactory implements ApplicationContextAware {
    
    
                // 缓存
                private static final Map<Integer, CreateShopStrategy> STRATEGY_MAP = new ConcurrentHashMap<>();
    
    
    
                /**
                 * 根据不同的type返回具体的策略
                 *
                 * @param type
                 * @return com.example.demos.strategy.CreateShopStrategy
                 * @author Reece
                 * @date 2022/4/10 19:39:19
                 */
                public CreateShopStrategy get(Integer type) {
                  // 从缓存中获取具体的实现类
                  return STRATEGY_MAP.get(type);
                }
    
    
                @Override
                public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
                  // 获取容器中所有实现CreateShopStrategy的实现类
                  Map<String, CreateShopStrategy> strategyMap = applicationContext.getBeansOfType(CreateShopStrategy.class);
    
                  // 设置进缓存中
                  strategyMap.values().forEach(strategy -> STRATEGY_MAP.put(strategy.getType(), strategy));
    
                }
              }
    

    验证

    上面已经完成了策略模式,剩下就是验证策略模式是否成功。

                /**
                 * @author Reece
                 * @Description
                 */
                @Service
                public class ShopServiceImpl implements ShopService {
    
    
                  @Autowired
                  private CreateShopStrategyFactory shopStrategyFactory;
    
    
                  @Override
                  public ShopVO createShop(CreateShopReqVO reqVO) {
    
                    // 获取具体的实现策略
                    CreateShopStrategy createShopStrategy = shopStrategyFactory.get(reqVO.getType());
                    // 获取返回值
                    return createShopStrategy.createShop(reqVO);
                  }
    
                }
    
    
    
                /**
                 * @author Reece
                 * @Description
                 */
                @Controller
                @RequestMapping("/shop")
                public class ShopController {
    
    
                  @Autowired
                  private ShopService shopService;
    
    
    
                  @ResponseBody
                  @PostMapping("/createShop")
                  public ShopVO createShop(CreateShopReqVO reqVO) {
                    return shopService.createShop(reqVO);
                  }
                }
    

      启动SpringBoot应用,传入不同的参数调用接口。

      type为1时,如下所示:

    image-20220410205705268

      type为2时,如下所示:

    image-20220410205639454

      至此,策略模式已完成,详细的源码请点击demos查看

  • 相关阅读:
    CAP 与数据一致性
    C++的构造函数为何不能为虚函数
    构造函数和析构函数中可以调用调用虚函数吗
    HTTP状态码
    C++ 单例模式实现
    【转】十大经典排序算法
    C++ short/int/long/long long 等数据类型大小
    块/文件/对象三种存储的优缺点
    罗振宇《时间的朋友》2019-2020
    Google Hacking
  • 原文地址:https://www.cnblogs.com/reecelin/p/16127507.html
Copyright © 2020-2023  润新知