设计模式组件设计开发

总结一下之前的开发实践,参考网上开源项目实现的设计模式组件开发😊😊😊

封装构造者模式

Builder 模式,强调的是 管理依赖关系或者约束条件

构建者模式相对简单,仅需要提供一个抽象接口即可。构建者相关的特性均在实现类中完成。

java 复制代码
 package org.opengoofy.index12306.framework.starter.designpattern.builder;
 ​
 import java.io.Serializable;
 ​
 /**
  * Builder 模式抽象接口
  *
  * @公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
  */
 public interface Builder<T> extends Serializable {
 ​
     /**
      * 构建方法
      *
      * @return 构建后的对象
      */
     T build();
 }

封装责任链模式

什么是责任链:举个例子,SpringMvc 中可以定义拦截器,并且可以定义多个。当一个用户发起请求时,顺利的话请求会经过所有拦截器,最终到达业务代码逻辑,SpringMvc 拦截器设计就是使用了责任链模式

前置校验是非常重要的环节。下面是一个可能的校验步骤列表:

前置校验是非常重要的环节。下面是一个可能的校验步骤列表:

  • 检查商品信息是否存在,包括商品名称、价格、规格等信息。
  • 检查购买数量是否合法,是否超出了最大购买数量或最小购买数量的限制。
  • 检查商品库存是否充足,以确保库存足够满足购买者的需求。
  • 检查购买者的优惠券、积分等是否可以使用,以确保购买者能够享受相应的优惠或积分奖励。
  • 检查收货地址信息是否完整和准确,以确保商品能够顺利地送达给购买者。
  • 检查下单时间是否合法,例如检查购买者是否在限定的时间范围内下单。

首先定义一个处理器接口继承Spring 框架中的排序接口 Ordered。这将有助于保证责任链中的任务顺序执行。

csharp 复制代码
 public interface OrderCreateChainHandler<T> extends Ordered {
     
     /**
      * 执行责任链逻辑
      *
      * @param requestParam 责任链执行入参
      */
     void handler(T requestParam);
 }

创建多个具体的执行器对象,写处理逻辑

创建一个责任链上下文容器,用于存储与责任链相应的执行器对象:

typescript 复制代码
 /**
  * 抽象责任链上下文
  *
  */
 public final class AbstractChainContext<T> implements CommandLineRunner {
 ​
     private final Map<String, List<AbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();
 ​
     /**
      * 责任链组件执行
      *
      * @param mark         责任链组件标识
      * @param requestParam 请求参数
      */
     public void handler(String mark, T requestParam) {
         List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
         if (CollectionUtils.isEmpty(abstractChainHandlers)) {
             throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
         }
         abstractChainHandlers.forEach(each -> each.handler(requestParam));
     }
 ​
     @Override
     public void run(String... args) throws Exception {
         Map<String, AbstractChainHandler> chainFilterMap = ApplicationContextHolder
                 .getBeansOfType(AbstractChainHandler.class);
         chainFilterMap.forEach((beanName, bean) -> {
             List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(bean.mark());
             if (CollectionUtils.isEmpty(abstractChainHandlers)) {
                 abstractChainHandlers = new ArrayList();
             }
             abstractChainHandlers.add(bean);
             List<AbstractChainHandler> actualAbstractChainHandlers = abstractChainHandlers.stream()
                     .sorted(Comparator.comparing(Ordered::getOrder))
                     .collect(Collectors.toList());
             abstractChainHandlerContainer.put(bean.mark(), actualAbstractChainHandlers);
         });
     }
 }

逻辑:在Spring程序启动后首先获取所有的AbstractChainHandler执行器的实例,按照名称将实例保存到map中,然后遍历这个map,根据mark标识获取所有的这个执行器的集合,并按照顺序保存在map中

使用:将这个AbstractChainContext注入到业务中,调用handler方法来依次执行各个组件

封装策略模式

定义抽象策略处理接口,添加有返回值和无返回值接口。

csharp 复制代码
 package org.opengoofy.congomall.springboot.starter.designpattern.strategy;
 ​
 /**
  * 策略执行抽象
  */
 public interface AbstractExecuteStrategy<REQUEST, RESPONSE> {
 ​
     /**
      * 执行策略标识
      */
     String mark();
 ​
     /**
      * 执行策略
      *
      * @param requestParam 执行策略入参
      */
     default void execute(REQUEST requestParam) {
 ​
     }
 ​
     /**
      * 执行策略,带返回值
      *
      * @param requestParam 执行策略入参
      * @return 执行策略后返回值
      */
     default RESPONSE executeResp(REQUEST requestParam) {
         return null;
     }
 }

添加策略选择器,通过订阅 Spring 初始化事件执行扫描所有策略模式接口执行器,并根据 mark 方法定义标识添加到 abstractExecuteStrategyMap 容器中。

客户端在实际业务中使用 AbstractStrategyChoose#choose 即可完成策略模式实现。

typescript 复制代码
 /**
  * 策略选择器
  */
 public class AbstractStrategyChoose implements ApplicationListener<ApplicationInitializingEvent> {
 ​
     /**
      * 执行策略集合
      */
     private final Map<String, AbstractExecuteStrategy> abstractExecuteStrategyMap = new HashMap<>();
 ​
     /**
      * 根据 mark 查询具体策略
      *
      * @param mark 策略标识
      * @return 实际执行策略
      */
     public AbstractExecuteStrategy choose(String mark) {
         return Optional.ofNullable(abstractExecuteStrategyMap.get(mark)).orElseThrow(() -> new ServiceException(String.format("[%s] 策略未定义", mark)));
     }
 ​
     /**
      * 根据 mark 查询具体策略并执行
      *
      * @param mark         策略标识
      * @param requestParam 执行策略入参
      * @param <REQUEST>    执行策略入参范型
      */
     public <REQUEST> void chooseAndExecute(String mark, REQUEST requestParam) {
         AbstractExecuteStrategy executeStrategy = choose(mark);
         executeStrategy.execute(requestParam);
     }
 ​
     /**
      * 根据 mark 查询具体策略并执行,带返回结果
      *
      * @param mark         策略标识
      * @param requestParam 执行策略入参
      * @param <REQUEST>    执行策略入参范型
      * @param <RESPONSE>   执行策略出参范型
      * @return
      */
     public <REQUEST, RESPONSE> RESPONSE chooseAndExecuteResp(String mark, REQUEST requestParam) {
         AbstractExecuteStrategy executeStrategy = choose(mark);
         return (RESPONSE) executeStrategy.executeResp(requestParam);
     }
 ​
     @Override
     public void onApplicationEvent(ApplicationInitializingEvent event) {
         Map<String, AbstractExecuteStrategy> actual = ApplicationContextHolder.getBeansOfType(AbstractExecuteStrategy.class);
         actual.forEach((beanName, bean) -> {
             AbstractExecuteStrategy beanExist = abstractExecuteStrategyMap.get(bean.mark());
             if (beanExist != null) {
                 throw new ServiceException(String.format("[%s] Duplicate execution policy", bean.mark()));
             }
             abstractExecuteStrategyMap.put(bean.mark(), bean);
         });
     }
 }
相关推荐
颜淡慕潇36 分钟前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决
尘浮生2 小时前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
尚学教辅学习资料2 小时前
基于SpringBoot的医药管理系统+LW示例参考
java·spring boot·后端·java毕业设计·医药管理
monkey_meng3 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马3 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng3 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
paopaokaka_luck7 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
码农小旋风9 小时前
详解K8S--声明式API
后端
Peter_chq9 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml49 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍