Java 责任链模式详解

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

核心角色:

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

优点:

降低请求发送者和接收者之间的耦合度
可以动态调整责任链结构
符合开闭原则,新增处理者无需修改原有代码

Java 责任链模式示例

下面以员工报销审批流程为例实现责任链模式:
组长可审批 ≤1000 元的报销
部门经理可审批 ≤5000 元的报销
总经理可审批 ≤10000 元的报销

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() + " 元报销无人能审批");
            }
        }
    }


}



//组长 张三 批准了 员工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 请求通过一系列中间件(如路由、认证、静态文件处理)组成的管道,每个中间件可决定是否将请求传递给下一个
    特点:处理流程呈流水线式,每个节点专注于特定处理步骤。
    责任链模式的核心优势
    解耦:请求发送者无需知道具体由哪个处理者处理,只需交给链的入口
    灵活性:可动态增删处理者或调整链的顺序,符合开闭原则
    单一职责:每个处理者只关注自己职责范围内的逻辑
    当需要「多个对象处理同一类请求,且处理者的选择需要动态决定」时,责任链模式是最佳选择之一。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐