《解锁高效流程设计:深度剖析责任链模式与实战应用》

《解锁高效流程设计:深度剖析责任链模式与实战应用》

责任链模式 是一种行为设计模式,它允许多个对象来处理请求,而不预先指定具体的处理者。多个处理对象被连接成一条链,沿着这条链传递请求,直到某个处理对象决定处理这个请求为止。责任链模式通过将请求的发送者与接收者解耦,来提高系统的灵活性。

UML 类图:责任链模式

在这里插入图片描述

角色说明

  1. Handler(抽象处理者):定义处理请求的接口,通常包含一个 setNext() 方法用于设置下一个处理者,以及 handleRequest() 方法处理请求或将其传递给下一个处理者。
  2. ConcreteHandler(具体处理者):具体处理请求的类。如果它能处理请求则直接处理,否则将请求传递给下一个处理者。
  3. Request(请求对象):请求对象,包含一些必要的信息,具体的处理者会根据请求中的信息决定是否处理。

实战场景:重构权限审批流程

问题描述

在企业内部的权限审批系统中,不同的人员可以审批不同级别的权限请求。例如:

  • 普通员工只能审批简单权限(如普通数据访问权限)。
  • 部门主管可以审批更高级别的权限请求(如敏感数据访问权限)。
  • 管理层可以审批最高级别的权限请求(如系统管理权限)。

当一个权限请求发出后,它会沿着审批链传递,直到找到能处理该请求的人员。使用责任链模式,可以让请求沿着处理链传递,并且避免将处理逻辑硬编码在某个具体对象中。

代码实现:权限审批流程的责任链构建

Step 1: 定义请求类

首先,我们定义一个 Request 类来封装权限请求。

// 请求类:封装权限请求
public class Request {private String requestType;private int permissionLevel;public Request(String requestType, int permissionLevel) {this.requestType = requestType;this.permissionLevel = permissionLevel;}public String getRequestType() {return requestType;}public int getPermissionLevel() {return permissionLevel;}
}

Step 2: 定义抽象处理者

定义抽象的 Handler 接口,所有具体的处理者都实现该接口。该接口定义了 setNext() 方法用于设置下一个处理者,handleRequest() 方法用于处理请求或将请求传递给下一个处理者。

// 抽象处理者接口
public abstract class Handler {protected Handler nextHandler;// 设置下一个处理者public void setNext(Handler nextHandler) {this.nextHandler = nextHandler;}// 抽象方法:处理请求public abstract void handleRequest(Request request);
}

Step 3: 实现具体的处理者

根据实际的权限审批流程,我们创建三个具体的处理者:普通员工、部门主管、管理层。

普通员工处理者

普通员工只能处理权限级别为 1 的请求。

// 具体处理者:普通员工
public class EmployeeHandler extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getPermissionLevel() == 1) {System.out.println("Employee approves request for: " + request.getRequestType());} else {if (nextHandler != null) {nextHandler.handleRequest(request);}}}
}
部门主管处理者

部门主管可以处理权限级别为 2 的请求。

// 具体处理者:部门主管
public class SupervisorHandler extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getPermissionLevel() == 2) {System.out.println("Supervisor approves request for: " + request.getRequestType());} else {if (nextHandler != null) {nextHandler.handleRequest(request);}}}
}
管理层处理者

管理层可以处理权限级别为 3 的请求。

// 具体处理者:管理层
public class ManagerHandler extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getPermissionLevel() == 3) {System.out.println("Manager approves request for: " + request.getRequestType());} else {System.out.println("Request not approved. No handler for permission level: " + request.getPermissionLevel());}}
}

Step 4: 创建处理链并测试

我们可以创建处理链,并将权限请求传递给链中的第一个处理者。

public class ChainOfResponsibilityDemo {public static void main(String[] args) {// 创建处理者Handler employee = new EmployeeHandler();Handler supervisor = new SupervisorHandler();Handler manager = new ManagerHandler();// 设置责任链employee.setNext(supervisor);supervisor.setNext(manager);// 创建权限请求Request request1 = new Request("Access to ordinary data", 1);Request request2 = new Request("Access to sensitive data", 2);Request request3 = new Request("System admin access", 3);Request request4 = new Request("Access to confidential data", 4);  // 没有处理者能处理// 开始处理请求employee.handleRequest(request1);  // 应由普通员工处理employee.handleRequest(request2);  // 应由部门主管处理employee.handleRequest(request3);  // 应由管理层处理employee.handleRequest(request4);  // 没有处理者能处理}
}

输出结果

Employee approves request for: Access to ordinary data
Supervisor approves request for: Access to sensitive data
Manager approves request for: System admin access
Request not approved. No handler for permission level: 4

责任链模式解决的问题

1.解耦请求发送者和接收者

  • 请求的发送者不知道请求的最终处理者是谁,处理者可以动态地决定是否处理请求或将请求传递给下一个处理者。

2.灵活的责任分配

  • 通过责任链的方式,可以动态地增加或减少处理者。系统可以根据实际需要自由调整处理链,增强了系统的灵活性。

3.避免代码的条件分支嵌套

  • 通过将责任分布在不同的处理者中,避免了大量的 if-elseswitch-case 语句,代码变得更加清晰且易于维护。

责任链模式的应用场景

  1. 审批流程
    • 比如企业的请假审批、费用报销审批流程。不同的审批人员有不同的权限,依次审批请求。
  2. 日志处理
    • 日志系统可以通过责任链模式,将日志消息依次传递给不同的处理者(如文件日志处理器、数据库日志处理器等)。
  3. 事件处理系统
    • GUI 事件处理,比如用户点击按钮时,会沿着事件链将事件分发给不同的事件处理器,直到事件被处理

SpringMVC 源码中的责任链模式剖析

责任链模式 在 SpringMVC 中被广泛使用,特别是在处理 HTTP 请求的过程中。SpringMVC 通过一系列的拦截器链过滤器链处理器适配器链等来解耦请求的处理方式,这些链条中的各个元素会根据自身职责处理请求或将其传递给下一个元素,这种设计非常符合责任链模式的思想。

接下来我们将剖析 SpringMVC 中责任链模式的几个典型应用场景,包括:

  1. DispatcherServlet 的处理链
  2. HandlerInterceptor 拦截器链
  3. HandlerExceptionResolver 处理器链

1. DispatcherServlet 的处理链

背景:

DispatcherServlet 是 SpringMVC 的核心,它作为前端控制器,负责接收 HTTP 请求并将其分发给合适的处理器进行处理。DispatcherServlet 并不是直接处理请求的,它依赖一系列的处理器链,包括处理器映射(HandlerMapping)处理器适配器(HandlerAdapter) 等。这些组件的设计符合责任链模式的思想。

工作流程:
  1. DispatcherServlet 接收请求后,会依次调用配置的多个 HandlerMapping 来找到合适的处理器。
  2. 找到处理器后,依次调用配置的多个 HandlerAdapter 来处理该处理器。
  3. 若请求处理失败,DispatcherServlet 会依次调用配置的 HandlerExceptionResolver 来处理异常。

通过这种链式调用,SpringMVC 将处理器映射、处理器适配和异常处理等职责分散到多个组件中,使得请求的处理过程高度灵活。

关键代码剖析:
  • 处理器映射链DispatcherServlet 中调用 getHandler() 方法时,会遍历所有配置的 HandlerMapping,并找到合适的处理器。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;
}

剖析

  • handlerMappings 是一个 HandlerMapping 列表,SpringMVC 允许配置多个 HandlerMapping,每个 HandlerMapping 都可以处理不同的请求映射。
  • getHandler() 会遍历所有 HandlerMapping,如果一个 HandlerMapping 可以处理当前请求,它就会返回对应的处理器,否则请求会被传递给下一个 HandlerMapping

这里的处理器映射链就是一个典型的责任链模式,每个 HandlerMapping 相当于一个链条上的处理者。

处理器适配器链: 找到处理器后,DispatcherServlet 会使用 HandlerAdapter 来执行该处理器的业务逻辑。SpringMVC 支持多种类型的处理器(如控制器、异步处理等),因此需要通过不同的 HandlerAdapter 来处理不同类型的处理器。

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}throw new ServletException("No adapter for handler [" + handler + "]");
}

剖析

  • handlerAdapters 是一个 HandlerAdapter 列表,每个 HandlerAdapter 都可以处理不同类型的处理器。
  • getHandlerAdapter() 会依次遍历 HandlerAdapter 列表,找到可以处理当前处理器的适配器,并使用它来执行处理器。
  • 这种处理器适配器的机制也是典型的责任链模式应用,不同的 HandlerAdapter 负责处理不同类型的请求处理器。

总结

优点:

  1. 降低耦合度:请求的发送者与接收者解耦,发送者不需要知道请求是由哪个具体的处理者处理的。
  2. 动态组合:可以灵活地增加或修改处理者链中的处理者,处理链的结构可以在运行时动态修改。
  3. 符合开闭原则:新的处理者可以很容易地加入到责任链中,不需要修改现有的处理者类。

缺点:

  1. 请求没有保证被处理:如果处理链中的所有处理者都没有处理请求,可能会导致请求未被处理的情况。
  2. 性能问题:如果责任链过长,可能会导致处理请求的效率降低,因为每个请求可能要经过多个处理者。

责任链模式 提供了一种灵活的处理请求的方式,通过将多个处理者连接成一条链,使得请求可以沿着链传递,直到被处理。通过使用责任链模式,我们可以解耦请求的发送者和处理者,并且可以动态增加或修改处理者,增强了系统的扩展性。

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

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

相关文章

SOMEIP_ETS_130: SD_Multicast_FindService_with_unicast_Flag_to_0

测试目的: 验证DUT能够忽略带有设置为0的单播标志的多播FindService请求,并以单播OfferService消息作为响应。 描述 本测试用例旨在确保DUT在接收到一个设置了单播标志为0的多播FindService请求时,能够忽略该标志并按照SOME/IP协议的要求&…

旧衣回收小程序搭建,开发功能优势

随着人们生活水平、消费水平的提高,在日常生活中产生了大量的限制物品,为了减少浪费,越来越多的人开始重视环保回收。旧衣物作为一种新型的回收方式,也逐渐得到了大众的关注,旧衣物回收市场发展规模也在持续上升&#…

【C++】STL详解之string类

目录 什么是STL STL的版本 STL的六大组件 STL的缺陷 一.string的定义方式 二. string的插入 1.使用push_back进行尾插 2.使用insert插入 三.string的拼接 四.string的删除 1.使用pop_back进行尾删 2.使用erase进行删除 五.string的查找 1.使用find正向搜索第一个…

快速排序(plus)与单调栈道,力扣912.排序数组​​​​​​​力扣215.数组中的第k大个元素力扣17.14最小的k个数单调栈力扣.柱状图中最大的矩形

目录 力扣912.排序数组​​​​​​​ 力扣215.数组中的第k大个元素 力扣17.14最小的k个数 单调栈 力扣.柱状图中最大的矩形 力扣912.排序数组 快速排序:最重要的就是数据划分,叫做partation left往后走,假如遇到比key小的,left是因为&a…

解释器模式原理剖析和Spring中的应用

解释器模式原理剖析和Spring中的应用 解释器模式 是一种行为型设计模式,它定义了一种语言的文法表示,并提供了一个解释器来处理该文法的表达式。解释器模式可以用于构建语法解释器,例如计算器、简单编程语言的解释器等。 核心思想&#xff1a…

My_String完善

#include "my_string_ok.h" My_string_Ok::My_string_Ok():size(20) { len 0; ptr new char[size]; ptr[len] \0; } My_string_Ok::My_string_Ok(int num,char c) { cout<<"有参构造"<<endl; ptr new char [20] ; len 0; for…

深度学习技术在超材料科学中的应用与实操

人工智能算法赋能材料设计与应用专题培训 前沿背景 人工智能与材料科学的融合趋势&#xff1a;在材料科学领域&#xff0c;人工智能&#xff08;AI&#xff09;的引入正在引发一场革命。传统的材料设计和优化依赖于经验和试错方法&#xff0c;这不仅耗时且成本高昂。关于AI赋…

安科瑞Acrel-1000DP分布式光伏监控系统在鄂尔多斯市鄂托克旗巴音乌苏六保煤矿5MW分布式光伏项目中的应用

安科瑞 华楠 摘 要&#xff1a;分布式光伏发电就是将太阳能光伏板分散布置在各个区域&#xff0c;通过小规模、模块化的方式实现电能的并网或独立使用&#xff0c;这种发电方式具有就近发电、就近并网、就近转换、就近使用的特点。近年来&#xff0c;技术进步和政策支持推动了光…

Python批量合并365个工作表的2种方法

一、引言 小明刚进入到新公司&#xff0c;就被委以重任&#xff1a;将365个Excel文件中的英文表头修改为中文。传统方法是逐一打开每个文件&#xff0c;手动修改标题&#xff0c;然后保存&#xff0c;最后再合并。这种方法不仅耗时耗力&#xff0c;还容易出错。如果用Python就…

下水道内缺陷识别检测数据集 yolo数据集 共2300张

下水道内缺陷识别检测数据集 yolo数据集 共2300张 下水道内部缺陷识别数据集&#xff08;Sewer Interior Defect Recognition Dataset, SIDRD&#xff09; 摘要 SIDRD 是一个专门针对下水道内部缺陷识别的数据集&#xff0c;旨在为城市基础设施维护和管理提供一个标准化的训练…

Qt:关于16进制数转化那些事

前言 由于当时做UDP通信的时候使用16进制数与QString的相互转换&#xff0c;但是当时我所要求的转换不仅仅是转化过去就行了&#xff0c;我还有字节数要求&#xff0c;就是这个16进制数占据多少位那么转化后的数据就该占据多大的空间。 正文 1 将 QString 转换为16进制字符串…

【Redis入门到精通五】Java如何像使用MySQL一样使用Redis(jedis安装及使用)

目录 Jedis 1.jedis是什么 2.jedis的安装配置 3.jedis的基础命令操作展示 1.set和get操作&#xff1a; 2.exists和del操作&#xff1a; 3.keys和type操作&#xff1a; 4. expire和ttl&#xff1a; Jedis Java 操作 redis 的客⼾端有很多&#xff0c;其中最知名的是 jedi…

STM32基础学习笔记-Timer定时器面试基础题5

第五章、TIMER 常见问题 1、基本概念&#xff1a;什么是定时器 &#xff1f;作用 &#xff1f;分类 &#xff1f; 2、时基单元 &#xff1f;组成 &#xff1f;计数模式 &#xff1f;溢出条件 &#xff1f; 溢出时间计算 &#xff1f; 3、systick原理 &#xff1f;代码讲解 &…

中国蚁剑(antSword)安装使用

antSword下载 antSword-Loader下载 作者&#xff1a;程序那点事儿 日期&#xff1a;2024/09/12 19:35 中国蚁剑&#xff08;AntSword&#xff09;是一款跨平台的开源网站管理工具&#xff0c;旨在满足渗透测试人员的需求。它是一个功能强大的工具&#xff0c;可以帮助用户管理…

基于CPS CPSQ5453CPSQ5352的易冲车灯方案

一、方案描述 CPS易冲&#xff08;CONVENIENTPOWER&#xff09;针对汽车矩阵大灯&#xff0c;推出 基于CPS CPSQ5453 & CPSQ5352的汽车矩阵式大灯方案。 开发板搭载的主要器件有CPS的独立双通道恒压恒流升压控制器&#xff1a;CPSQ5453、独立双通道LED恒流降压变换器&#…

心觉:如何重塑高效学习的潜意识(1)两种方法的优缺点

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作180/1000天 你的学习习惯是什么呢 学习的时候是感到轻松吗 很多人感觉现在是知识大爆炸的时代&#xff0c;每天都会产生海量的知…

第 1 章:Vue 核心

1. Vue 简介 1.1. 官网 英文官网: https://vuejs.org/中文官网: https://cn.vuejs.org/&#xff1a;中文官网里面【教程】和【API】是比较重要的。用到api就去查询&#xff0c;实践当中记忆更牢靠。 风格指南&#xff1a;官方推荐写的一个代码风格cookbook&#xff1a;编写v…

【Python报错已解决】SyntaxError: invalid syntax

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25 1. PromSec: Prompt Optimization for Secure Generation of Functional Source Code with Large Language Models (LLMs) M Nazzal, I Khalil, A Khreishah, NH Phan - arXiv preprint arXiv:2409.12699, 2…

车辆识别数据集,图片数量20500,模型已训练200轮

车辆识别数据集&#xff08;Vehicle Recognition Dataset, VDRD&#xff09; 摘要 VDRD 是一个专为车辆识别设计的大规模数据集&#xff0c;它包含了20500张不同类型的汽车、货车、公交车以及其他类型车辆的图像。数据集提供了四种车辆类别&#xff1a;汽车、货车、其他车辆和…