当前位置: 首页 > news >正文

设计模式之责任链模式

        责任链模式是一种经典的设计模式,属于行为型设计模式,他的核心思想是:将请求的发起者与接受者进行解耦,让多个对象都有机会处理请求,从而避免了请求发送者与接受者之间的耦合关系。这些对象连接形成一条链,请求沿着这条链传递,直到被某个对象处理为止。

        你会简单的发现,在这种处理模式直线,实际上是有先后顺序的,你可以把它想象成为一个链表,从头到尾开始进行执行,在某一步执行完毕之后结束返回,下面我将举一个具体的业务场景来具体说明当前模式

业务场景

        我们需要计算一下两个地点的运费,但是对于每个地点的运费的计算规则是不同的,也就是我们现在设计了多个模板,你需要进行判断然后返回需要的模板,下面给出逻辑示意图

解决

        你会发现当我们给出逻辑示意图的时候,整个思路就比较明确了,你可以写许多的ifelse,但是这样的话你的代码会显得比较冗余并且拓展性极差,所以我们基于任务链设计模式来解决

首先,我们定义抽象类处理链对象,你可以认为实际上就是指向下一个的指针,也就是说,当你的是否同城判断完之后,如果成功就返回,不成功就执行下一个节点

package com.sl.ms.carriage.handler;import com.sl.ms.carriage.domain.dto.WaybillDTO;
import com.sl.ms.carriage.entity.CarriageEntity;/*** 运费模板处理链的抽象定义*/
public abstract class AbstractCarriageChainHandler {private AbstractCarriageChainHandler nextHandler;/*** 执行过滤方法,通过输入参数查找运费模板** @param waybillDTO 输入参数* @return 运费模板*/public abstract CarriageEntity doHandler(WaybillDTO waybillDTO);/*** 执行下一个处理器** @param waybillDTO     输入参数* @param carriageEntity 上个handler处理得到的对象* @return*/protected CarriageEntity doNextHandler(WaybillDTO waybillDTO, CarriageEntity carriageEntity) {if (nextHandler == null || carriageEntity != null) {//如果下游Handler为空 或 上个Handler已经找到运费模板就返回return carriageEntity;}return nextHandler.doHandler(waybillDTO);}/*** 设置下游Handler** @param nextHandler 下游Handler*/public void setNextHandler(AbstractCarriageChainHandler nextHandler) {this.nextHandler = nextHandler;}
}

然后,你这个时候就是去定义同城,同省,同经济区的既可

这边写一个同城的

package com.sl.ms.carriage.handler;import com.sl.ms.carriage.domain.constant.CarriageConstant;
import com.sl.ms.carriage.domain.dto.WaybillDTO;
import com.sl.ms.carriage.entity.CarriageEntity;
import com.sl.ms.carriage.service.CarriageService;
import com.sl.transport.common.util.ObjectUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** 同城寄*/
@Order(100) //定义顺序
@Component
public class SameCityChainHandler extends AbstractCarriageChainHandler {@Resourceprivate CarriageService carriageService;@Overridepublic CarriageEntity doHandler(WaybillDTO waybillDTO) {CarriageEntity carriageEntity = null;if (ObjectUtil.equals(waybillDTO.getReceiverCityId(), waybillDTO.getSenderCityId())) {//同城carriageEntity = this.carriageService.findByTemplateType(CarriageConstant.SAME_CITY);}return doNextHandler(waybillDTO, carriageEntity);}
}

你会发现,这里我们在最后在一次调用了doNextHandler,也就是传给了下一个节点,

这个时候开始组装处理链

package com.sl.ms.carriage.handler;import cn.hutool.core.collection.CollUtil;
import com.sl.ms.carriage.domain.dto.WaybillDTO;
import com.sl.ms.carriage.entity.CarriageEntity;
import com.sl.transport.common.exception.SLException;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;/*** 查找运费模板处理链 @Order注解指定handler顺序*/
@Component
public class CarriageChainHandler {/*** 利用Spring注入特性,按照 @Order 从小到达排序注入到集合中*/@Resourceprivate List<AbstractCarriageChainHandler> chainHandlers;private AbstractCarriageChainHandler firstHandler;/*** 组装处理链*/@PostConstructprivate void constructChain() {if (CollUtil.isEmpty(chainHandlers)) {throw new SLException("not found carriage chain handler!");}//处理链中第一个节点firstHandler = chainHandlers.get(0);for (int i = 0; i < chainHandlers.size(); i++) {if (i == chainHandlers.size() - 1) {//最后一个处理链节点chainHandlers.get(i).setNextHandler(null);} else {//设置下游节点chainHandlers.get(i).setNextHandler(chainHandlers.get(i + 1));}}}public CarriageEntity findCarriage(WaybillDTO waybillDTO) {//从第一个节点开始处理return firstHandler.doHandler(waybillDTO);}}

我们对于最后一个节点的下一个节点设置为null,对于每个节点的下一个节点,我们实际上是由先后顺序的,我们可以基于spring对于每一个类写上order注解进行排序,spring的抽象类在进行注入的时候,会根据order的值从小到大注入,这样我们之后调用find方法就可以解决当前的业务问题了

总结

  • 责任链模式是一种行为型设计模式,用于解耦请求发送者和接收者。
  • 核心思想​:将多个处理者连接成一条链,请求沿着链传递,直到被某个处理者处理。
  • 适用场景​:Web 过滤器、审批流程、异常处理、日志记录等。
  • 优点​:解耦、灵活、符合单一职责原则。
  • 缺点​:请求可能未被处理,调试较复杂。
http://www.xdnf.cn/news/1059355.html

相关文章:

  • 《仿盒马》app开发技术分享--未完成订单列表展示逻辑优化(61)
  • SKUA-GOCAD入门教程-第八节 线的创建与编辑5
  • C/Fortran多核并行计算
  • wireshark过滤器的使用
  • tomcat 配置规范
  • stack 和 queue练习
  • 【面试题001】生产环境中如何排查MySQL CPU占用率高达100%?
  • linux kernel优化之rootfs
  • CANFD加速是什么?和CANFD有什么区别?
  • linux 下 jenkins 构建 uniapp node-sass 报错
  • 使用@SpringJUnitConfig注解开发遇到的空指针问题
  • spring-webmvc @InitBinder 典型用法
  • 《挑战你的控制力!开源项目小游戏学习“保持平衡”开发解析:用HTML+JS+CSS实现物理平衡挑战》​
  • 【51单片机】8. 矩阵LED显示自定义图案、动画
  • 用idea操作git缓存区回退、本地库回退、远程库回退
  • singlefligt使用方法和源码解读
  • 无需公网IP:Termux+手机+内网穿透实现Minecraft远程多人联机
  • Uniapp 中根据不同离开页面方式处理 `onHide` 的方法
  • python3:线程管理进程
  • 前端打断点
  • python校园服务交流系统
  • 第十八天:初级数据库学习笔记2
  • easyexcel基于模板生成报表
  • RabbitMQ七种工作模式
  • 21.加密系统函数
  • macOS版的节点小宝上架苹果APP Store了
  • git的使用——初步认识git和基础操作
  • DeepForest开源程序是用于 Airborne RGB 机器学习的 Python 软件包
  • 使用 Elasticsearch 提升 Copilot 能力
  • [计算机网络] 网络的诞生:协议的认知建立