当前位置: 首页 > news >正文

Java设计模式:责任链模式

一、什么是责任链模式?

责任链模式(Chain of Responsibility Pattern) 是一种 行为型设计模式,它通过将请求沿着一条处理链传递,直到某个对象处理它为止。这种模式的核心思想是 解耦请求的发送者和接收者,使多个对象都有机会处理请求,避免请求发送者与具体处理者之间的紧耦合。

核心角色

  • 抽象处理者(Handler)

    • 定义处理请求的接口,包含一个指向下一个处理者的引用(nextHandler)。
    • 提供设置后续处理者的方法(setNextHandler),用于构建责任链。
  • 具体处理者(ConcreteHandler)

    • 实现抽象处理者的处理方法,判断自己是否有权限处理请求:
      • 若有权,处理请求并结束流程;
      • 若无权,将请求传递给后续处理者(nextHandler.handleRequest)。
  • 客户端(Client)

    • 创建责任链,并向链的起点发送请求,无需知道具体是哪个处理者处理了请求。

二、责任链模式的核心思想

责任链模式的核心是 “链式传递”“责任分配” 的分离。

  • 链式传递:请求从链的起点开始,依次传递给每个处理者,直到某个处理者处理它。
  • 责任分配:每个处理者只负责自己职责范围内的请求,超出范围的请求则传递给下一个处理者。

生活中的例子

想象你在公司提交一个报销申请,流程如下:

  1. 直接主管审批(1000元以下);
  2. 部门经理审批(1000-5000元);
  3. 财务总监审批(5000元以上)。
    这就是一个典型的责任链模式,每个审批人只处理自己权限范围内的请求,超出权限则传递给下一个审批人。

三、Java实现责任链模式

1. 基础示例:请假审批系统

(1)定义抽象处理者

// 抽象处理者类:定义了处理请求的接口和设置下一个处理者的方法
public abstract class LeaveHandler {// 持有下一个处理者的引用,形成链式结构protected LeaveHandler nextHandler;// 设置下一个处理者public void setNextHandler(LeaveHandler nextHandler) {this.nextHandler = nextHandler;}// 抽象方法:具体处理者需要实现该方法来处理请求public abstract void handleRequest(LeaveRequest request);
}

(2)定义具体处理者

// 具体处理者:小组长,处理1-3天的请假请求
public class TeamLeader extends LeaveHandler {@Overridepublic void handleRequest(LeaveRequest request) {// 判断是否在自己的处理范围内if (request.getDays() <= 3) {System.out.println("小组长批准了 " + request.getName() + " 的 " + request.getDays() + " 天请假");} else if (nextHandler != null) {// 超出处理范围且存在下一个处理者,将请求传递nextHandler.handleRequest(request);} else {// 没有合适的处理者System.out.println("无人能处理该请求");}}
}// 具体处理者:经理,处理3-7天的请假请求
public class Manager extends LeaveHandler {@Overridepublic void handleRequest(LeaveRequest request) {// 判断是否在自己的处理范围内if (request.getDays() <= 7) {System.out.println("经理批准了 " + request.getName() + " 的 " + request.getDays() + " 天请假");} else if (nextHandler != null) {// 超出处理范围且存在下一个处理者,将请求传递nextHandler.handleRequest(request);} else {// 没有合适的处理者System.out.println("无人能处理该请求");}}
}// 具体处理者:总监,处理7天以上的请假请求
public class Director extends LeaveHandler {@Overridepublic void handleRequest(LeaveRequest request) {// 判断是否在自己的处理范围内if (request.getDays() > 7) {System.out.println("总监批准了 " + request.getName() + " 的 " + request.getDays() + " 天请假");} else if (nextHandler != null) {// 超出处理范围且存在下一个处理者,将请求传递nextHandler.handleRequest(request);} else {// 没有合适的处理者System.out.println("无人能处理该请求");}}
}

(3)定义请求类

// 请假请求类:封装了请假的相关信息
public class LeaveRequest {private String name;  // 请假人姓名private int days;     // 请假天数private String reason; // 请假原因public LeaveRequest(String name, int days, String reason) {this.name = name;this.days = days;this.reason = reason;}// 以下是获取请假信息的方法public String getName() { return name; }public int getDays() { return days; }public String getReason() { return reason; }
}

(4)客户端调用

// 客户端类:构建责任链并提交请求
public class Client {public static void main(String[] args) {// 1. 构建责任链:按照 小组长 -> 经理 -> 总监 的顺序设置LeaveHandler teamLeader = new TeamLeader();LeaveHandler manager = new Manager();LeaveHandler director = new Director();// 设置责任链顺序teamLeader.setNextHandler(manager);manager.setNextHandler(director);// 2. 创建请假请求LeaveRequest request1 = new LeaveRequest("张三", 2, "生病");  // 2天请假,应由小组长处理LeaveRequest request2 = new LeaveRequest("李四", 10, "家庭事务"); // 10天请假,应由总监处理// 3. 提交请求到责任链的起点(小组长)// 当调用 teamLeader.handleRequest(request1) 时:// - 小组长判断2天 <=3天,直接处理该请求teamLeader.handleRequest(request1);// 当调用 teamLeader.handleRequest(request2) 时:// - 小组长判断10天 >3天,将请求传递给经理// - 经理判断10天 >7天,将请求传递给总监// - 总监判断10天 >7天,处理该请求teamLeader.handleRequest(request2);}
}

⑸、流程图和内存图

2.责任链模式的经典实现

下面通过一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限:

(1)定义抽象处理者

// Approver.java
public abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者public void setSuccessor(Approver successor) {this.successor = successor;}// 处理请求的抽象方法public abstract void processRequest(PurchaseRequest request);
}

(2)定义具体处理者

// Director.java
public class Director extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 10000) {System.out.println("主任审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}

// Manager.java
public class Manager extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 50000) {System.out.println("经理审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}

// VicePresident.java
public class VicePresident extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 100000) {System.out.println("副总裁审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}

// President.java
public class President extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 500000) {System.out.println("总裁审批了金额为 " + request.getAmount() + " 的采购申请");} else {System.out.println("金额过大,需要董事会讨论");}}
}

(3)定义请求类

// PurchaseRequest.java
public class PurchaseRequest {private double amount; // 金额private String purpose; // 用途public PurchaseRequest(double amount, String purpose) {this.amount = amount;this.purpose = purpose;}public double getAmount() {return amount;}public String getPurpose() {return purpose;}
}

(4)客户端调用

// Client.java
public class Client {public static void main(String[] args) {// 创建处理者Approver director = new Director();Approver manager = new Manager();Approver vicePresident = new VicePresident();Approver president = new President();// 设置责任链director.setSuccessor(manager);manager.setSuccessor(vicePresident);vicePresident.setSuccessor(president);// 创建采购申请PurchaseRequest request1 = new PurchaseRequest(5000, "购买办公用品");PurchaseRequest request2 = new PurchaseRequest(30000, "购买电脑设备");PurchaseRequest request3 = new PurchaseRequest(80000, "购买服务器");PurchaseRequest request4 = new PurchaseRequest(300000, "购买办公大楼");// 处理请求director.processRequest(request1);director.processRequest(request2);director.processRequest(request3);director.processRequest(request4);}
}

在这个示例中,我们创建了一个审批链,从主任到经理、副总裁,最后到总裁。每个审批者根据自己的权限处理请求,如果无法处理则将请求传递给下一个审批者。客户端只需要将请求发送给链头的处理者,无需关心具体是哪个处理者最终处理了请求。


能不能连写?return this;返回的是谁


四、责任链模式在 Java 中的实际应用

责任链模式在 Java 中有许多实际应用场景,例如:

  1. Servlet 过滤器链:在 Java Web 应用中,Servlet 过滤器可以形成一个链,每个过滤器负责特定的任务,如编码转换、权限验证等。
  2. 日志记录系统:不同级别的日志可以由不同的处理器处理,如控制台日志、文件日志、数据库日志等。
  3. 异常处理链:多个异常处理器可以按顺序尝试处理异常。

下面是一个使用 Java 8 函数式编程简化责任链模式的示例:

import java.util.function.Consumer;public class FunctionalChainExample {public static void main(String[] args) {// 定义处理者Consumer<String> logger = message -> System.out.println("日志记录: " + message);Consumer<String> authChecker = message -> {if (message.contains("admin")) {System.out.println("权限验证通过");} else {System.out.println("权限验证失败");}};Consumer<String> processor = message -> System.out.println("处理请求: " + message);// 构建责任链Consumer<String> chain = logger.andThen(authChecker).andThen(processor);// 处理请求chain.accept("admin:create_user");chain.accept("user:view_profile");}
}

这个示例使用 Java 8 的函数式接口和方法引用简化了责任链的实现,使代码更加简洁和灵活。

责任链模式的优缺点

优点:

  • 降低了请求发送者和接收者之间的耦合度。
  • 可以动态添加或修改处理者,提高了系统的灵活性。
  • 简化了对象间的连接,每个对象只需保持一个后续者引用。

缺点:

  • 请求可能无法被处理,因为链中没有合适的处理者。
  • 如果责任链过长,可能会影响系统性能。
  • 调试时可能会比较困难,因为请求的处理过程是隐式的。

总结

责任链模式是一种非常实用的设计模式,它将请求的发送者和接收者解耦,使多个处理者都有机会处理请求。通过合理地使用责任链模式,可以提高系统的灵活性和可维护性。在实际开发中,我们可以根据具体需求选择传统的实现方式或使用函数式编程进行简化。无论是 Servlet 过滤器链还是日志处理系统,责任链模式都能发挥其独特的优势。

相关文章:

  • Linux 特殊权限位详解:SetUID, SetGID, Sticky Bit
  • 数据结构第一章
  • 【RAG优化】rag整体优化建议
  • [ Qt ] | 与系统相关的操作(二):键盘、定时器、窗口移动和大小
  • 跟着deepseek浅学分布式事务(2) - 两阶段提交(2PC)
  • yum更换阿里云的镜像源
  • 保险丝选型
  • 树莓派系列教程第九弹:Cpolar内网穿透搭建NAS
  • 云数据库选型指南:关系型 vs NoSQL vs NewSQL的企业决策
  • 【开源工具】 黑客帝国系列系统监控工具:基于PyQt5的全方位资源监控系统
  • 【Linux】编译器gcc/g++及其库的详细介绍
  • 【从GEO数据库批量下载数据】
  • Python训练打卡Day42
  • YOLOv1 到 YOLOv12汇总信息2025.6.4
  • Python绘图库及图像类型
  • [Linux] Linux GPIO应用编程深度解析与实践指南(代码示例)
  • Flutter如何支持原生View
  • 【PDF提取表格】如何提取发票内容文字并导出到Excel表格,并将发票用发票号改名,基于pdf电子发票的应用实现
  • 【Linux】自动化构建-Make/Makefile
  • 模拟搭建私网访问外网、外网访问服务器服务的实践操作
  • 网站底部素材/windows优化大师在哪里
  • wordpress forum/seo站长综合查询
  • 如何在工商局网站做企业年报/seo关键字优化
  • 想做个自己的网站/广州网站建设系统
  • 静态网站建设/网店推广是什么
  • 衡水教育行业网站建设/河北百度竞价优化