设计模式组件设计开发

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

封装构造者模式

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);
         });
     }
 }
相关推荐
ZSYP-S12 分钟前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
Yuan_o_1 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
程序员一诺1 小时前
【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
后端·python
DT辰白2 小时前
如何解决基于 Redis 的网关鉴权导致的 RESTful API 拦截问题?
后端·微服务·架构
thatway19892 小时前
AI-SoC入门:15NPU介绍
后端
陶庵看雪2 小时前
Spring Boot注解总结大全【案例详解,一眼秒懂】
java·spring boot·后端
Q_19284999063 小时前
基于Spring Boot的图书管理系统
java·spring boot·后端
ss2733 小时前
基于Springboot + vue实现的汽车资讯网站
vue.js·spring boot·后端
一只IT攻城狮3 小时前
华为云语音交互SIS的使用案例(文字转语音-详细教程)
java·后端·华为云·音频·语音识别
星月前端4 小时前
springboot中使用gdal将表中的空间数据转shapefile文件
java·spring boot·后端