23种设计模式之【责任链模式】-核心原理与 Java 实践

文章目录

Java 责任链模式详解

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过构建一个处理者对象链,使请求能够在链中传递,直到有一个处理者能够处理该请求为止。

核心角色:

抽象处理者(Handler):定义处理请求的接口,包含一个指向下一个处理者的引用
具体处理者(ConcreteHandler):实现处理请求的方法,判断能否处理当前请求,如果可以则处理,否则将请求传递给下一个处理者
请求(Request):包含需要处理的信息

优点:

降低请求发送者和接收者之间的耦合度

可以动态调整责任链结构

符合开闭原则,新增处理者无需修改原有代码

Java 责任链模式示例

下面以员工报销审批流程为例实现责任链模式:

组长可审批 ≤1000 元的报销

部门经理可审批 ≤5000 元的报销

总经理可审批 ≤10000 元的报销

java 复制代码
public class TestZenRenLian {


        public static void main(String[] args) {
            // 创建各个审批者
            Approver teamLeader = new TeamLeader("张三");
            Approver deptManager = new DepartmentManager("李四");
            Approver generalManager = new GeneralManager("王五");

            // 构建责任链:组长→部门经理→总经理
            teamLeader.setNextApprover(deptManager);
            deptManager.setNextApprover(generalManager);

            // 创建报销请求
            Reimbursement request1 = new Reimbursement("员工A", 800);
            Reimbursement request2 = new Reimbursement("员工B", 3000);
            Reimbursement request3 = new Reimbursement("员工C", 8000);
            Reimbursement request4 = new Reimbursement("员工D", 15000);  // 超过最大审批权限

            // 处理请求
            teamLeader.processReimbursement(request1);
            teamLeader.processReimbursement(request2);
            teamLeader.processReimbursement(request3);
            teamLeader.processReimbursement(request4);
        }

    // 报销请求类
    public static class Reimbursement {
        private String name;  // 申请人
        private double amount;  // 报销金额

        public Reimbursement(String name, double amount) {
            this.name = name;
            this.amount = amount;
        }

        public String getName() {
            return name;
        }

        public double getAmount() {
            return amount;
        }
    }

    // 抽象处理者类
    public abstract static class Approver {
        protected Approver nextApprover;  // 下一个审批人
        protected String name;  // 审批人姓名

        public Approver(String name) {
            this.name = name;
        }

        // 设置下一个审批人
        public void setNextApprover(Approver nextApprover) {
            this.nextApprover = nextApprover;
        }

        // 处理报销请求的抽象方法
        public abstract void processReimbursement(Reimbursement request);
    }

    // 组长(处理≤1000元的报销)
    public static class TeamLeader extends Approver {

        public TeamLeader(String name) {
            super(name);
        }

        @Override
        public void processReimbursement(Reimbursement request) {
            if (request.getAmount() <= 1000) {
                System.out.println("组长 " + name + " 批准了 " + request.getName() +
                        " 的 " + request.getAmount() + " 元报销");
            } else if (nextApprover != null) {
                // 超过权限,传递给下一个审批人
                nextApprover.processReimbursement(request);
            } else {
                System.out.println(request.getName() + " 的 " + request.getAmount() + " 元报销无人能审批");
            }
        }
    }

    // 部门经理(处理≤5000元的报销)
    public static class DepartmentManager extends Approver {

        public DepartmentManager(String name) {
            super(name);
        }

        @Override
        public void processReimbursement(Reimbursement request) {
            if (request.getAmount() <= 5000) {
                System.out.println("部门经理 " + name + " 批准了 " + request.getName() +
                        " 的 " + request.getAmount() + " 元报销");
            } else if (nextApprover != null) {
                nextApprover.processReimbursement(request);
            } else {
                System.out.println(request.getName() + " 的 " + request.getAmount() + " 元报销无人能审批");
            }
        }
    }

    // 总经理(处理≤10000元的报销)
    public static class GeneralManager extends Approver {

        public GeneralManager(String name) {
            super(name);
        }

        @Override
        public void processReimbursement(Reimbursement request) {
            if (request.getAmount() <= 10000) {
                System.out.println("总经理 " + name + " 批准了 " + request.getName() +
                        " 的 " + request.getAmount() + " 元报销");
            } else if (nextApprover != null) {
                nextApprover.processReimbursement(request);
            } else {
                System.out.println(request.getName() + " 的 " + request.getAmount() + " 元报销无人能审批");
            }
        }
    }


}
java 复制代码
//组长 张三 批准了 员工A 的 800.0 元报销
//部门经理 李四 批准了 员工B 的 3000.0 元报销
//总经理 王五 批准了 员工C 的 8000.0 元报销
//员工D 的 15000.0 元报销无人能审批

代码解析

  • Reimbursemen请求信息类:封装了报销请求的信息,包括申请人姓名和报销金额
  • Approver 抽象类:
    定义了所有审批者的共同行为
    包含一个 nextApprover 引用,用于指向下一个审批者
    提供了设置下一个审批者的方法 setNextApprover()
    声明了处理报销请求的抽象方法 processReimbursement()
  • 具体处理者:
    每个处理者只处理自己权限范围内的请求
    若无法处理,则将请求传递给下一个处理者
    形成了 "组长→部门经理→总经理" 的处理链

经典应用场景

责任链模式在实际开发中有许多经典应用场景,其核心是「将请求的发送者与处理者解耦,让多个处理者有机会依次处理请求」。以下是一些常见的应用场景:

  1. 审批流程场景
    这是责任链模式最典型的应用,如:
    请假审批:员工请假 → 小组长审批(≤3 天)→ 部门经理审批(≤7 天)→ 总经理审批(≤30 天)
    报销审批:金额从小到大,依次由组长、部门经理、财务总监等逐级审批
    公文流转:文件按级别依次经过不同部门或职位处理
    特点:每个处理者有明确的权限范围,超出则传递给下一级。
  2. 过滤器 / 拦截器场景
    在 Web 开发中,过滤器(Filter)或拦截器(Interceptor)链是责任链模式的经典实现:
    Servlet Filter:请求到达目标资源前,会经过多个过滤器(如编码过滤、登录验证、权限检查、XSS 过滤等),每个过滤器可决定是否继续传递请求
    Spring Interceptor:对 Controller 方法的调用进行拦截,可依次执行预处理、后处理等操作
    日志过滤:不同级别(Debug、Info、Warn、Error)的日志处理器依次判断是否需要记录日志
    特点:每个处理者专注于单一职责(如验证、过滤、转换),可动态组合顺序。
  3. 事件传递场景
    在 GUI 或事件驱动开发中,事件会沿着组件层级传递:
    GUI 组件事件:如按钮点击事件,会先由按钮自身处理,若未处理则传递给父容器(面板→窗口→应用程序)
    Android 事件分发:触摸事件从 View 到 ViewGroup 再到 Activity 的传递链,每个层级可决定是否消费事件或继续传递
    特点:事件沿层级链传递,上层组件可覆盖下层处理逻辑。
  4. 异常处理场景
    在异常处理中,不同的异常处理器可形成责任链:
    异常捕获链:代码中多个catch块实际上构成了责任链,从具体异常到通用异常依次匹配(如先捕获NullPointerException,再捕获Exception)
    自定义异常处理器:系统中注册多个异常处理器,依次尝试处理异常,直到被处理或抛出
    特点:按异常类型的范围从小到大依次处理。
  5. 请求处理管道(Pipeline)
    在框架或中间件中,请求处理常设计为管道模式(本质是责任链的变种):
    Netty 的 ChannelPipeline:网络请求在 Handler 链中依次经过编码、解码、业务处理等步骤
    ASP.NET Core 中间件:HTTP 请求通过一系列中间件(如路由、认证、静态文件处理)组成的管道,每个中间件可决定是否将请求传递给下一个
    特点:处理流程呈流水线式,每个节点专注于特定处理步骤。
    责任链模式的核心优势
    解耦:请求发送者无需知道具体由哪个处理者处理,只需交给链的入口
    灵活性:可动态增删处理者或调整链的顺序,符合开闭原则
    单一职责:每个处理者只关注自己职责范围内的逻辑
    当需要「多个对象处理同一类请求,且处理者的选择需要动态决定」时,责任链模式是最佳选择之一。
相关推荐
萧瑟余晖42 分钟前
JDK 26 新特性详解
java·开发语言
马优晨1 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
维天说4 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19945 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
杨充5 小时前
11.DDD与战术建模
设计模式·开源·代码规范
杨充5 小时前
12.综合实战图片框架
设计模式·开源·代码规范
噢,我明白了5 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品5 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘5 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记6 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端