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

devtools/2024/9/29 18:09:37/

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

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

UML 类图:责任链模式

在这里插入图片描述

角色说明

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

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

问题描述

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

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

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

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

Step 1: 定义请求类

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

java">// 请求类:封装权限请求
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() 方法用于处理请求或将请求传递给下一个处理者。

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

Step 3: 实现具体的处理者

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

普通员工处理者

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

java">// 具体处理者:普通员工
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 的请求。

java">// 具体处理者:部门主管
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 的请求。

java">// 具体处理者:管理层
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: 创建处理链并测试

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

java">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);  // 没有处理者能处理}
}

输出结果

java">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,并找到合适的处理器。
java">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 来处理不同类型的处理器。

java">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.ppmy.cn/devtools/118814.html

相关文章

git拉代码时,远程也对文件进行了更改,后面如何操作

解决方法: 1.git stash 把当前未提交的修改暂存起来,让仓库还原到最后一次提交的状态。 2.git pull 拉取远程仓库的代码,让你现在的代码和远程仓库一致 3.git stash pop 放开暂存,恢复当前未提交的修改

Spring Boot使用配置方式整合MyBatis

文章目录 一、实战目标二、步骤概览1. 创建部门映射器接口2. 创建映射器配置文件3. 配置全局映射器4. 测试映射器接口 三、详细步骤1、创建部门映射器接口2、创建映射器配置文件3、配置全局映射器4、测试映射器接口 四、结语 一、实战目标 在本实战课程中,我们将学…

2024年配置YOLOX运行环境+windows+pycharm24.0.1+GPU

1.配置时间2024/9/25 2.Anaconda-python版本3.7,yolox版本0.2.0 YOLOX网址: https://github.com/Megvii-BaseDetection/YOLOX 本人下载的这个版本 1.创建虚拟环境 conda create -n yolox37 python37 激活 conda activate yolox37 2.安装Pytorch cuda等&…

关于PHP 匿名函数在处理数据结构中的应用

PHP 的匿名函数(也称为闭包)在处理数据结构时非常有用。它们可以在需要一次性函数的情况下使用,例如数组函数的回调、事件处理或作为其他函数的参数。以下是一些常见的应用场景: 数组操作: 使用 array_map、array_fil…

【RabbitMQ——SpringBoot整合】

1. fanout模式 Fanout 交换器(Exchange)是 RabbitMQ 中的一种消息路由模式。它是一种广播式的交换器,会将接收到的消息发送给所有绑定到该交换器的队列,而不考虑路由键(routing key)。这意味着无论消息发布…

边缘计算网关:轻工行业的智能化新引擎

在轻工行业迈向智能化转型的浪潮中,边缘计算网关作为关键技术载体,正逐步展现其不可替代的作用。这一前沿技术,通过在数据源附近进行高效数据处理与分析,不仅加速了数据价值挖掘,还推动了生产流程的优化与效率的提升。…

c语言和c++一样吗

C语言和C并不一样,尽管它们有很多相似之处。以下是一些主要区别: 编程范式 C语言:主要是一种过程式编程语言,强调函数和过程。 C:支持面向对象编程(OOP),引入了类、对象、继承、多态…

用通义灵码如何快速合理解决遗留代码问题?

本文首先介绍了遗留代码的概念,并对遗留代码进行了分类。针对不同类型的遗留代码,提供了相应的处理策略。此外,本文重点介绍了通义灵码在维护遗留代码过程中能提供哪些支持。 什么是遗留代码 与过时技术相关的代码: 与不再受支持的…