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

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

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

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 {

    @Override
    public 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 {

    @Override
    public 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 {

    @Override
    public 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. 性能问题:如果责任链过长,可能会导致处理请求的效率降低,因为每个请求可能要经过多个处理者。

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

相关推荐
天天扭码3 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶4 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺8 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
zwjapple14 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five16 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序16 分钟前
vue3 封装request请求
java·前端·typescript·vue
前端每日三省17 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
凡人的AI工具箱31 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
陈王卜33 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、34 分钟前
Spring Boot 注解
java·spring boot