设计模式探索:责任链模式

news2024/11/16 20:35:21

1. 什么是责任链模式

责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下:

  • 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。
  • 将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
    在这里插入图片描述

2. 责任链模式的作用

  • 将请求和请求的处理进行解耦,提高代码的可扩展性。

3. 责任链模式的结构

在这里插入图片描述

责任链模式主要包含以下角色:

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接(链上的每个处理者都有一个成员变量来保存对于下一处理者的引用)。
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

在实际开发中,责任链模式可能会增加一个责任链管理者来管理具体的处理者。

4. 责任链模式在实际开发中的应用

在 SpringBoot 中,责任链模式的实践方式有多种,以下是一种示例:一个下单流程的多个独立检查逻辑。
在这里插入图片描述

4.1 实现方式1
  1. 创建 Pojo, 下单对象
public class OrderContext {
    private String seqId;
    private String userId;
    private Long skuId;
    private Integer amount;
    private String userAddressId;
    // Getters and setters
}
  1. 创建处理者接口
public interface OrderHandleIntercept {
    int sort();
    OrderContext handle(OrderContext context);
}
  1. 创建具体处理者类
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {
    @Override
    public int sort() {
        return 1; // 执行顺序为 1
    }

    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("通过seqId,检查客户是否重复下单");
        return context;
    }
}

@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {
    @Override
    public int sort() {
        return 2; // 执行顺序为 2
    }

    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("检查请求参数是否合法,并且获取客户的银行账户");
        return context;
    }
}

@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {
    @Override
    public int sort() {
        return 3; // 执行顺序为 3
    }

    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
        return context;
    }
}
  1. 处理器链类
@Component
public class OrderHandleChainService implements ApplicationContextAware {
    private List<OrderHandleIntercept> handleList = new ArrayList<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, OrderHandleIntercept> serviceMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);
        handleList = serviceMap.values().stream()
                .sorted(Comparator.comparing(OrderHandleIntercept::sort))
                .collect(Collectors.toList());
    }

    public OrderContext execute(OrderContext context) {
        for (OrderHandleIntercept handleIntercept : handleList) {
            context = handleIntercept.handle(context);
        }
        return context;
    }
}
  1. 进行单元测试
@Autowired
private OrderHandleChainService orderHandleChainService;

@Test
public void test02() {
    orderHandleChainService.execute(new OrderContext());
}
  1. 执行结果
通过seqId,检查客户是否重复下单
检查请求参数是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额
4.2 实现方式2

通过注解 @Order 来指定排序

@Order(1)
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {
    //...省略
}

@Order(2)
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {
    //...省略
}

@Order(3)
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {
    //...省略
}

修改 OrderHandleChainService

@Component
public class OrderHandleChainService {

    @Autowired
    private List<OrderHandleIntercept> handleList;

    public OrderContext execute(OrderContext context) {
        for (OrderHandleIntercept handleIntercept : handleList) {
            context = handleIntercept.handle(context);
        }
        return context;
    }
}
4.3 实现方式3

通过定义抽象类来实现责任链设计模式

public abstract class AbstractOrderHandle {

    private AbstractOrderHandle next;

    public AbstractOrderHandle getNext() {
        return next;
    }

    public void setNext(AbstractOrderHandle next) {
        this.next = next;
    }

    public abstract OrderContext handle(OrderContext orderContext);

    public OrderContext execute(OrderContext context) {
        context = handle(context);
        if (getNext() != null) {
            getNext().execute(context);
        }
        return context;
    }
}

分别创建处理类

@Component
@Order(1)
public class RepeatOrderHandle extends AbstractOrderHandle {
    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("通过seqId,检查客户是否重复下单");
        return context;
    }
}

@Component
@Order(2)
public class ValidOrderHandle extends AbstractOrderHandle {
    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");
        return context;
    }
}

@Component
@Order(3)
public class BankOrderHandle extends AbstractOrderHandle {
    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
        return context;
    }
}

创建一个责任链管理器

@Component
public class OrderHandleManager {

    @Autowired
    private List<AbstractOrderHandle> orderHandleList;

    @PostConstruct
    public void initChain() {
        int size = orderHandleList.size();
        for (int i = 0; i < size; i++) {
            if (i == size - 1) {
                orderHandleList.get(i).setNext(null);
            } else {
                orderHandleList.get(i).setNext(orderHandleList.get(i + 1));
            }
        }
    }

    public OrderContext execute(OrderContext context) {
        OrderContext execute = orderHandleList.get(0).execute(context);
        return context;
    }
}

测试

@Autowired
private OrderHandleManager orderHandleManager;

@Test
public void test02() {
    orderHandleManager.execute(new OrderContext());
}

运行结果与预期一致:

通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额

5. 职责链模式总结

职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。这种模式为请求的处理提供了一条清晰的链,每个对象可以决定是否处理该请求或者将请求转发给链中的下一个对象。

职责链模式的优点:

  1. 降低耦合度:发送者和接收者之间没有直接的联系,降低了系统组件之间的耦合度。
  2. 增强灵活性:可以在运行时动态地添加或移除职责链中的处理对象,提高了系统的灵活性和可扩展性。
  3. 明确责任分配:每个处理对象只关注自己的职责范围,责任分配更加明确。

职责链模式的缺点:

  1. 请求处理不确定性:不能保证请求一定会被处理,如果链中的所有对象都不处理请求,请求将被忽略。
  2. 系统性能影响:请求可能需要通过较长的链进行传递,可能会对性能产生影响。
  3. 客户端复杂性增加:客户端可能需要了解整个职责链的配置,增加了客户端的使用复杂性。

职责链模式的使用场景:

  1. 多个对象处理请求:当一个请求需要多个对象依次处理时,可以使用职责链模式。
  2. 处理逻辑不明确:在运行时根据请求的类型动态选择处理对象,不希望客户端知道具体的处理逻辑。

职责链模式的实现可以通过组合多个具体处理者对象,并设置它们的后继者,形成一个处理链。当请求发出时,链中的每个对象依次判断是否能够处理该请求,如果可以处理则执行处理操作,否则将请求转发给链中的下一个对象。

这种模式在实际应用中非常广泛,例如在GUI应用程序的事件处理、工作流审批流程、过滤器链等场景中都有应用。通过使用职责链模式,可以提高系统的模块化和灵活性,同时降低组件之间的依赖关系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1919634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数列分块<2>

本期是数列分块入门<2>。该系列的所有题目来自hzwer在LOJ上提供的数列分块入门系列。 Blog:http://hzwer.com/8053.html sto hzwer orz %%% [转载] 好像上面的链接↑打不开&#xff0c;放一个转载:https://www.cnblogs.…

CUDA原子操作

代码 #include <cuda_runtime.h> #include <stdio.h>__global__ void atomicAddAndGet(int *result, int *valueToAdd) {// 原子加法int addedValue atomicAdd(result, *valueToAdd);// 通过原子操作后读取值&#xff0c;确保是加法后的值addedValue *valueToAd…

LabVIEW开发CAN总线多传感器液位检测系统

设计并实现了一个基于CAN总线和LabVIEW的多传感器液位检测系统。该系统利用STM32F107单片机进行模拟信号与数字信号的转换&#xff0c;通过TJA1050实现CAN总线通信&#xff0c;并使用USB-CAN分析仪连接PC。LabVIEW用于数据采集、人机交互界面的设计、数据分析和仪器标定。系统能…

前端必修技能:高手进阶核心知识分享 - 三万字帮你搞定CSS动画(形变动画、过渡动画、关键帧动画)

在CSS的世界里,存在着多种能体现动画效果的属性:CSS transform、CSS Transition 和 CSS Animation。让开始接触CSS的同学感到困惑。要搞清楚CSS的动画,我们就必须先把这几种属性做一下区别。 CSS transform 属性、CSS Transition 属性、 CSS Animation 属性的区别 CSS tra…

FL Studio21.5.3.21中文版破解安装包!音乐制作新神器,让创意无限飞扬!

&#x1f3b6; 音乐制作&#xff0c;轻松入门&#xff01;FL Studio21中文版本体验分享 嘿&#xff01;各位音乐小能手和创作小白们&#xff0c;今天我要给大家安利一个超酷炫的音乐制作软件——FL Studio21中文版&#xff01;&#x1f389; FL Studio21汉化版下载网盘链接: …

Python函数 之 模块和包---练习

题目 1 1.定义一个模块 toolls.py , 定义函数实现对两个数据进行加法操作的函数 add_2_num &#xff0c;并返回相加之和的结 果&#xff1b; 再定义一个实现对三个数据进行加法操作的函数 add_3_num &#xff0c;并返回相加之和的结果&#xff1b; 2.最后新定义一个代码文件 …

AutoMQ vs Kafka: 来自小红书的独立深度评测与对比

测试背景 当前小红书消息引擎团队与 AutoMQ 团队正在深度合作&#xff0c;共同推动社区建设&#xff0c;探索云原生消息引擎的前沿技术。本文基于 OpenMessaging 框架&#xff0c;对 AutoMQ 进行了全面测评。欢迎大家参与社区并分享测评体验。 01 测试结论 本文主要测评云…

JavaDS —— 单链表 与 LinkedList

顺序表和链表区别 ArrayList &#xff1a; 底层使用连续的空间&#xff0c;可以随机访问某下标的元素&#xff0c;时间复杂度为O&#xff08;1&#xff09; 但是在插入和删除操作的时候&#xff0c;需要将该位置的后序元素整体往前或者向后移动&#xff0c;时间复杂度为O&…

二分查找算法——部分OJ题详解

目录 关于二分查找算法 部分OJ题详解 704.二分查找 一&#xff0c;分析题目 二&#xff0c;细节处理 三&#xff0c;题目代码 四&#xff0c;*总结朴素模板 *34.在排序数组中查找元素的第一个和最后一个位置 一&#xff0c;查找左端点 二&#xff0c;处理左端点细…

ts实现将相同类型的数据通过排序放在一起

看下效果&#xff0c;可以将相同表名称的字段放在一起 排序适用于中英文、数字 // 排序 function sortByType(items: any) {// 先按照类型进行排序items.sort((a: any, b: any) > {if (a.label < b.label) return -1;if (a.label > b.label) return 1;return 0;});r…

【记录】LaTex|LaTex调整算法、公式、表格内的字体大小(10种内置字号)

文章目录 【记录】LaTex&#xff5c;LaTex调整算法、公式、表格内的字体大小&#xff08;10种内置字号&#xff09;省流版1 字体大小2 测试代码 详细版1 \tiny2 \scriptsize3 \footnotesize4 \small5 \normalsize6 \large7 \Large8 \LARGE9 \huge10 \Huge 【记录】LaTex&#x…

实验02 黑盒测试(组合测试、场景法)

1. 组合测试用例设计技术 指出等价类划分法和边界值分析法通常假设输入变量相互独立&#xff0c;但实际情况中变量间可能存在关联。全面测试&#xff1a;覆盖所有输入变量的所有可能组合&#xff0c;测试用例数量随输入变量的增加而指数增长。 全面测试需要对所有输入的各个取…

Geoserver源码解读六 插件

系列文章目录 Geoserver源码解读一 环境搭建 Geoserver源码解读二 主入口 Geoserver源码解读三 GeoServerBasePage Geoserver源码解读四 REST服务 Geoserver源码解读五 Catalog Geoserver源码解读六 插件&#xff08;怎么在开发模式下使用&#xff09; 目录 系列文章目…

ubuntu计划任务反弹

目录 实验环境 实验步骤 目标主机构造任务计划 构造语句 语句解释 kali开启监听 监听成功 问题 原因 实验环境 攻击者 操作系统&#xff1a;kali IP&#xff1a;192.168.244.141 目标主机 操作系统&#xff1a;ubuntu IP&#xff1a;192.168.244.151 实验步骤 目…

CSS 中的 ::before 和 ::after 伪元素

目录 一、CSS 伪元素 二、::before ::after 介绍 1、::before 2、::after 3、content 常用属性值 三、::before ::after 应用场景 1、设置统一字符 2、通过背景添加图片 3、添加装饰线 4、右侧展开箭头 5、对话框小三角 6、插入icon图标 一、CSS 伪元素 CSS伪元…

数据库使用SSL加密连接

简介 数据库开通SSL加密连接是确保数据传输过程中安全性的关键措施&#xff0c;它通过加密数据、验证服务器身份、保护敏感信息、维护数据完整性和可靠性&#xff0c;同时满足行业标准和法规要求&#xff0c;进而提升用户体验和信任度&#xff0c;为企业的数据安全和业务连续性…

做工和音质都堪称典范!悠律Ringbuds pro耳机动感低音享受

想要长时间佩戴舒适&#xff0c;又要听歌看电影音质好&#xff0c;还想户外运动时不影响听到环境声音&#xff0c;开放式毋容置疑是最好的选择&#xff0c;像我每天坐地铁上下班的时候都会习惯戴耳机&#xff0c;但以前戴入耳式耳机的时候经常会错过站点&#xff0c;耽误了不少…

TREK高压功率放大器维修trek高压电源609E-6

美国Trek维修产品包括&#xff1a;高压放大器、电源、静电电压表、高压功能发生器、放大器、静电测量仪、荷电板、信号放大器、高压电源、功率放大器、高压功能发生器、高压放大器、接触电压表、非接触式电压表、板载控制器、ESD和传感器、ESD电压表、带电板、电离器、表面电阻…

HashMap----源码解读

源码分析&#xff1a; public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable 在类的开头声明了几个常量&#xff0c;以下是较为重要的&#xff1a; /*** 定义初始容量大小为16*/ static final int DEFAULT_I…

【射频器件供应】 Marki Microwave

射频、微波和毫米波组件 裸片、表面贴装、连接器和波导 直流至Sub-THz Marki Microwave通过创建强大的性能突破性射频和微波组件产品组合&#xff0c;解决了业界最棘手的技术问题。Marki Microwave 成立于 1991 年&#xff0c;以开发业内最好的混频器为目标&#xff0c;如今已…