责任链设计模式详解
一、责任链模式概述
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理链传递,直到有一个处理者处理它。这种模式让多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
核心概念
- 处理者:定义处理请求的接口
- 具体处理者:实现处理请求的具体逻辑
- 链:将处理者连接起来,形成处理链
二、责任链模式的结构
2.1 UML 类图
┌─────────────┐ ┌─────────────────┐
│ Client │ │ Handler │
│ │ │ │
│ +main() │ │ +handleRequest()│
└─────────────┘ │ +setNext() │
│ └─────────────────┘
│ △
│ │
│ ┌─────────────────┐
└───────────│ ConcreteHandler │
│ │
│ +handleRequest()│
└─────────────────┘
2.2 核心角色
- Handler(抽象处理者):定义处理请求的接口
- ConcreteHandler(具体处理者):实现具体的处理逻辑
- Client(客户端):创建处理链并向链头发送请求
三、责任链模式的实现
3.1 基础实现
步骤1:定义抽象处理者
java
/**
* 抽象处理者 - 审批人
*/
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:定义请求对象
java
/**
* 采购请求 - 请求对象
*/
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:实现具体处理者
java
/**
* 具体处理者 - 部门经理
*/
public class DepartmentManager extends Approver {
public DepartmentManager(String name) {
super(name);
}
@Override
public 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);
}
@Override
public 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);
}
@Override
public 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:客户端使用
java
/**
* 客户端 - 测试责任链模式
*/
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 使用集合管理处理链
java
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;
}
@Override
public 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 支持中断的责任链
java
/**
* 支持中断的抽象处理者
*/
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;
}
@Override
public 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 链
java
// 模拟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 {
@Override
public 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 {
@Override
public 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 事件处理系统
java
/**
* 事件处理器链
*/
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
- 日志处理系统:不同级别的日志由不同处理器处理
- 数据验证链:多个验证规则依次执行
八、总结
责任链模式通过将请求的发送者和接收者解耦,提供了灵活的请求处理机制。在实际开发中,它特别适合于需要多级处理或动态处理流程的场景。
关键要点:
- 合理设计处理者的职责范围
- 注意处理链的长度,避免性能问题
- 考虑请求可能未被处理的情况
- 支持动态调整处理链的顺序和内容
通过合理运用责任链模式,可以构建出灵活、可扩展的处理系统,大大提高代码的可维护性和可扩展性。