责任链设计模式详解
责任链设计模式详解
一、责任链模式概述
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理链传递,直到有一个处理者处理它。这种模式让多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
核心概念
- 处理者:定义处理请求的接口
- 具体处理者:实现处理请求的具体逻辑
- 链:将处理者连接起来,形成处理链
二、责任链模式的结构
2.1 UML 类图
┌─────────────┐ ┌─────────────────┐
│ Client │ │ Handler │
│ │ │ │
│ +main() │ │ +handleRequest()│
└─────────────┘ │ +setNext() ││ └─────────────────┘│ △│ ││ ┌─────────────────┐└───────────│ ConcreteHandler ││ ││ +handleRequest()│└─────────────────┘
2.2 核心角色
- Handler(抽象处理者):定义处理请求的接口
- ConcreteHandler(具体处理者):实现具体的处理逻辑
- Client(客户端):创建处理链并向链头发送请求
三、责任链模式的实现
3.1 基础实现
步骤1:定义抽象处理者
/*** 抽象处理者 - 审批人*/
public abstract class Approver {protected Approver nextApprover; // 下一个处理者protected String name; // 处理者名称public Approver(String name) {this.name = name;}// 设置下一个处理者public Approver setNext(Approver nextApprover) {this.nextApprover = nextApprover;return this.nextApprover; // 返回下一个处理者,支持链式调用}// 处理审批请求的抽象方法public abstract void processRequest(PurchaseRequest request);
}
步骤2:定义请求对象
/*** 采购请求 - 请求对象*/
public class PurchaseRequest {private int type; // 请求类型private int number; // 请求编号private float price; // 金额private String purpose; // 用途public PurchaseRequest(int type, int number, float price, String purpose) {this.type = type;this.number = number;this.price = price;this.purpose = purpose;}// getter 方法public int getType() { return type; }public int getNumber() { return number; }public float getPrice() { return price; }public String getPurpose() { return purpose; }
}
步骤3:实现具体处理者
/*** 具体处理者 - 部门经理*/
public class DepartmentManager extends Approver {public DepartmentManager(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest request) {if (request.getPrice() <= 5000) {// 部门经理可以审批5000元以下的采购System.out.println("请求编号: " + request.getNumber() + ",金额: " + request.getPrice() + ",目的: " + request.getPurpose());System.out.println("审批人: " + this.name + " [部门经理]");} else if (nextApprover != null) {// 超过权限,传递给下一个处理者System.out.println("部门经理 " + name + " 无权审批,转交上级...");nextApprover.processRequest(request);} else {// 没有下一个处理者,审批失败System.out.println("请求无法处理,审批链结束");}}
}/*** 具体处理者 - 副总经理*/
public class ViceGeneralManager extends Approver {public ViceGeneralManager(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest request) {if (request.getPrice() <= 10000) {// 副总经理可以审批10000元以下的采购System.out.println("请求编号: " + request.getNumber() + ",金额: " + request.getPrice() + ",目的: " + request.getPurpose());System.out.println("审批人: " + this.name + " [副总经理]");} else if (nextApprover != null) {// 超过权限,传递给下一个处理者System.out.println("副总经理 " + name + " 无权审批,转交上级...");nextApprover.processRequest(request);} else {System.out.println("请求无法处理,审批链结束");}}
}/*** 具体处理者 - 总经理*/
public class GeneralManager extends Approver {public GeneralManager(String name) {super(name);}@Overridepublic void processRequest(PurchaseRequest request) {if (request.getPrice() <= 50000) {// 总经理可以审批50000元以下的采购System.out.println("请求编号: " + request.getNumber() + ",金额: " + request.getPrice() + ",目的: " + request.getPurpose());System.out.println("审批人: " + this.name + " [总经理]");} else {// 超过总经理权限,需要董事会审批System.out.println("金额过大(" + request.getPrice() + "),需要召开董事会讨论");}}
}
步骤4:客户端使用
/*** 客户端 - 测试责任链模式*/
public class ChainOfResponsibilityClient {public static void main(String[] args) {// 1. 创建处理者Approver departmentManager = new DepartmentManager("张经理");Approver viceManager = new ViceGeneralManager("李副总");Approver generalManager = new GeneralManager("王总经理");// 2. 构建责任链:部门经理 -> 副总经理 -> 总经理departmentManager.setNext(viceManager).setNext(generalManager);// 3. 创建不同的采购请求System.out.println("=== 测试责任链模式 ===");// 请求1:3000元,应该由部门经理审批PurchaseRequest request1 = new PurchaseRequest(1, 1001, 3000, "购买办公用品");System.out.println("\n请求1: 3000元采购");departmentManager.processRequest(request1);// 请求2:8000元,应该由副总经理审批PurchaseRequest request2 = new PurchaseRequest(2, 1002, 8000, "部门团队建设");System.out.println("\n请求2: 8000元采购");departmentManager.processRequest(request2);// 请求3:30000元,应该由总经理审批PurchaseRequest request3 = new PurchaseRequest(3, 1003, 30000, "购买服务器");System.out.println("\n请求3: 30000元采购");departmentManager.processRequest(request3);// 请求4:100000元,超过审批权限PurchaseRequest request4 = new PurchaseRequest(4, 1004, 100000, "公司车辆采购");System.out.println("\n请求4: 100000元采购");departmentManager.processRequest(request4);}
}
3.2 输出结果
=== 测试责任链模式 ===请求1: 3000元采购
请求编号: 1001,金额: 3000.0,目的: 购买办公用品
审批人: 张经理 [部门经理]请求2: 8000元采购
部门经理 张经理 无权审批,转交上级...
请求编号: 1002,金额: 8000.0,目的: 部门团队建设
审批人: 李副总 [副总经理]请求3: 30000元采购
部门经理 张经理 无权审批,转交上级...
副总经理 李副总 无权审批,转交上级...
请求编号: 1003,金额: 30000.0,目的: 购买服务器
审批人: 王总经理 [总经理]请求4: 100000元采购
部门经理 张经理 无权审批,转交上级...
副总经理 李副总 无权审批,转交上级...
金额过大(100000.0),需要召开董事会讨论
四、责任链模式的进阶实现
4.1 使用集合管理处理链
import java.util.ArrayList;
import java.util.List;/*** 处理链管理器*/
public class ApprovalChain {private List<Approver> approvers = new ArrayList<>();private int index = 0; // 当前处理者索引// 添加处理者public void addApprover(Approver approver) {approvers.add(approver);}// 处理请求public void processRequest(PurchaseRequest request) {if (index < approvers.size()) {Approver currentApprover = approvers.get(index);index++;currentApprover.processRequest(request);} else {System.out.println("所有处理者都无法处理该请求");}}// 重置链(支持重复使用)public void reset() {index = 0;}
}/*** 修改后的具体处理者(简化版)*/
public class SimpleApprover extends Approver {private double maxAmount;public SimpleApprover(String name, double maxAmount) {super(name);this.maxAmount = maxAmount;}@Overridepublic void processRequest(PurchaseRequest request) {if (request.getPrice() <= maxAmount) {System.out.println("审批通过: " + name + " 审批了 " + request.getPrice() + "元");} else if (nextApprover != null) {System.out.println(name + " 无法审批,转交下一级");nextApprover.processRequest(request);} else {System.out.println("无人能够审批该请求");}}
}// 使用示例
public class AdvancedChainExample {public static void main(String[] args) {// 创建处理链管理器ApprovalChain chain = new ApprovalChain();chain.addApprover(new SimpleApprover("经理", 5000));chain.addApprover(new SimpleApprover("总监", 20000));chain.addApprover(new SimpleApprover("总经理", 100000));// 处理多个请求PurchaseRequest[] requests = {new PurchaseRequest(1, 1001, 3000, "测试1"),new PurchaseRequest(2, 1002, 15000, "测试2"),new PurchaseRequest(3, 1003, 50000, "测试3"),new PurchaseRequest(4, 1004, 200000, "测试4")};for (PurchaseRequest request : requests) {System.out.println("\n处理请求: " + request.getPrice() + "元");chain.processRequest(request);chain.reset(); // 重置链以处理下一个请求}}
}
4.2 支持中断的责任链
/*** 支持中断的抽象处理者*/
public abstract class InterruptibleApprover {protected InterruptibleApprover nextApprover;public void setNext(InterruptibleApprover nextApprover) {this.nextApprover = nextApprover;}/*** 处理请求,返回true表示继续传递,false表示中断链*/public abstract boolean processRequest(PurchaseRequest request);
}/*** 具体处理者 - 支持中断*/
public class InterruptibleDepartmentManager extends InterruptibleApprover {private String name;public InterruptibleDepartmentManager(String name) {this.name = name;}@Overridepublic boolean processRequest(PurchaseRequest request) {if (request.getPrice() <= 5000) {System.out.println(name + " 审批了 " + request.getPrice() + "元");return false; // 审批完成,中断链} else if (request.getPurpose().contains("紧急")) {System.out.println(name + " 处理紧急请求: " + request.getPurpose());// 紧急请求需要所有领导知晓,但不中断链return true;} else {System.out.println(name + " 无法审批,转交上级");return true; // 继续传递}}
}
五、责任链模式在真实项目中的应用
5.1 Java Web 中的 Filter 链
// 模拟Servlet Filter的责任链实现
public interface Filter {void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);
}public class FilterChain {private List<Filter> filters = new ArrayList<>();private int index = 0;public void addFilter(Filter filter) {filters.add(filter);}public void doFilter(ServletRequest request, ServletResponse response) {if (index < filters.size()) {Filter filter = filters.get(index);index++;filter.doFilter(request, response, this);}// 链执行完毕,执行实际业务逻辑}
}// 具体过滤器
public class LoggingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {System.out.println("日志记录: " + new Date());chain.doFilter(request, response); // 继续下一个过滤器System.out.println("日志记录完成");}
}public class AuthFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {if (isAuthenticated(request)) {chain.doFilter(request, response);} else {// 认证失败,中断链System.out.println("认证失败");}}private boolean isAuthenticated(ServletRequest request) {// 认证逻辑return true;}
}
5.2 事件处理系统
/*** 事件处理器链*/
public class EventHandlerChain {private List<EventHandler> handlers = new ArrayList<>();public void addHandler(EventHandler handler) {handlers.add(handler);}public boolean handleEvent(Event event) {for (EventHandler handler : handlers) {if (handler.canHandle(event)) {handler.handle(event);return true; // 事件已处理}}return false; // 没有处理器能处理该事件}
}public interface EventHandler {boolean canHandle(Event event);void handle(Event event);
}
六、责任链模式的优缺点
优点:
- 降低耦合度:请求发送者不需要知道哪个对象会处理它的请求
- 增强灵活性:可以动态地增加或修改处理链
- 简化对象:每个处理者只需关注自己的责任范围
- 符合开闭原则:新增处理者无需修改现有代码
缺点:
- 请求可能未被处理:如果链中没有合适的处理者,请求可能得不到处理
- 性能影响:长链可能影响性能,特别是在链的遍历上
- 调试困难:请求的传递路径可能不直观,调试较复杂
七、适用场景
- 多级审批系统:如采购审批、请假审批等
- 事件处理系统:如GUI事件处理、异常处理
- 过滤器/拦截器链:如Web应用中的Filter、Interceptor
- 日志处理系统:不同级别的日志由不同处理器处理
- 数据验证链:多个验证规则依次执行
八、总结
责任链模式通过将请求的发送者和接收者解耦,提供了灵活的请求处理机制。在实际开发中,它特别适合于需要多级处理或动态处理流程的场景。
关键要点:
- 合理设计处理者的职责范围
- 注意处理链的长度,避免性能问题
- 考虑请求可能未被处理的情况
- 支持动态调整处理链的顺序和内容
通过合理运用责任链模式,可以构建出灵活、可扩展的处理系统,大大提高代码的可维护性和可扩展性。