什么是责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它将请求的发送者和接收者解耦,允许多个对象都有机会处理请求。这些对象连接成一条链,请求沿着链传递,直到有对象处理它为止。
责任链模式的核心思想是:将能够处理同一类请求的对象连成一条链,请求沿着这条链传递,直到链上的某个对象能够处理该请求。这样可以避免请求发送者与接收者之间的耦合关系。
责任链模式的结构
责任链模式包含以下主要角色:
- 处理者(Handler):定义一个处理请求的接口,通常包含对下一个处理者的引用
- 具体处理者(Concrete Handler):实现处理者接口,处理它负责的请求,可以访问下一个处理者
- 客户端(Client):创建处理链,并向链上的第一个处理者发送请求
责任链模式的基本实现
下面是责任链模式的基本Java实现:
// 请求类
class Request {
private String type;
private int amount;
public Request(String type, int amount) {
this.type = type;
this.amount = amount;
}
public String getType() {
return type;
}
public int getAmount() {
return amount;
}
}
// 处理者接口
interface Handler {
Handler setNext(Handler handler);
String handle(Request request);
}
// 抽象处理者类
abstract class AbstractHandler implements Handler {
private Handler next;
@Override
public Handler setNext(Handler handler) {
this.next = handler;
return handler; // 返回下一个处理者,支持链式调用
}
@Override
public String handle(Request request) {
if (next != null) {
return next.handle(request);
}
return "没有处理者可以处理该请求";
}
}
// 具体处理者:经理
class ManagerHandler extends AbstractHandler {
@Override
public String handle(Request request) {
if ("请假".equals(request.getType()) && request.getAmount() <= 3) {
return "经理已批准请假申请";
}
// 不能处理,传递给下一个处理者
return super.handle(request);
}
}
// 具体处理者:总监
class DirectorHandler extends AbstractHandler {
@Override
public String handle(Request request) {
if ("请假".equals(request.getType()) && request.getAmount() <= 7) {
return "总监已批准请假申请";
} else if ("经费".equals(request.getType()) && request.getAmount() <= 5000) {
return "总监已批准经费申请";
}
// 不能处理,传递给下一个处理者
return super.handle(request);
}
}
// 具体处理者:CEO
class CEOHandler extends AbstractHandler {
@Override
public String handle(Request request) {
if ("请假".equals(request.getType()) && request.getAmount() <= 14) {
return "CEO已批准请假申请";
} else if ("经费".equals(request.getType()) && request.getAmount() <= 50000) {
return "CEO已批准经费申请";
}
// 不能处理,传递给下一个处理者
return super.handle(request);
}
}
// 客户端代码
public class ChainOfResponsibilityDemo {
public static void main(String[] args) {
// 创建处理链
Handler manager = new ManagerHandler();
Handler director = new DirectorHandler();
Handler ceo = new CEOHandler();
// 设置责任链
manager.setNext(director).setNext(ceo);
// 创建请求
Request request1 = new Request("请假", 2);
Request request2 = new Request("请假", 5);
Request request3 = new Request("请假", 10);
Request request4 = new Request("请假", 20);
Request request5 = new Request("经费", 4000);
Request request6 = new Request("经费", 20000);
Request request7 = new Request("经费", 100000);
// 处理请求
System.out.println(manager.handle(request1)); // 经理处理
System.out.println(manager.handle(request2)); // 总监处理
System.out.println(manager.handle(request3)); // CEO处理
System.out.println(manager.handle(request4)); // 无人处理
System.out.println(manager.handle(request5)); // 总监处理
System.out.println(manager.handle(request6)); // CEO处理
System.out.println(manager.handle(request7)); // 无人处理
}
}
实际应用示例:日志记录器
下面通过一个日志记录系统来展示责任链模式的实际应用:
// 日志级别枚举
enum LogLevel {
INFO(1), DEBUG(2), ERROR(3);
private int level;
LogLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
// 日志对象
class LogMessage {
private LogLevel level;
private String message;
public LogMessage(LogLevel level, String message) {
this.level = level;
this.message = message;
}
public LogLevel getLevel() {
return level;
}
public String getMessage() {
return message;
}
}
// 抽象日志处理器
abstract class LoggerHandler {
protected LogLevel level;
protected LoggerHandler next;
public LoggerHandler(LogLevel level) {
this.level = level;
}
// 设置下一个处理者
public LoggerHandler setNext(LoggerHandler next) {
this.next = next;
return next;
}
// 处理日志消息
public void log(LogMessage logMessage) {
if (logMessage.getLevel().getLevel() >= this.level.getLevel()) {
writeLog(logMessage);
}
if (next != null) {
next.log(logMessage);
}
}
// 由具体子类实现的写日志方法
protected abstract void writeLog(LogMessage logMessage);
}
// 控制台日志处理器
class ConsoleLogger extends LoggerHandler {
public ConsoleLogger(LogLevel level) {
super(level);
}
@Override
protected void writeLog(LogMessage logMessage) {
System.out.println("控制台日志:" + logMessage.getLevel() + " - " + logMessage.getMessage());
}
}
// 文件日志处理器
class FileLogger extends LoggerHandler {
public FileLogger(LogLevel level) {
super(level);
}
@Override
protected void writeLog(LogMessage logMessage) {
System.out.println("文件日志:" + logMessage.getLevel() + " - " + logMessage.getMessage());
}
}
// 数据库日志处理器
class DatabaseLogger extends LoggerHandler {
public DatabaseLogger(LogLevel level) {
super(level);
}
@Override
protected void writeLog(LogMessage logMessage) {
System.out.println("数据库日志:" + logMessage.getLevel() + " - " + logMessage.getMessage());
}
}
// 客户端代码
public class LoggerExample {
public static void main(String[] args) {
// 创建日志处理链
LoggerHandler consoleLogger = new ConsoleLogger(LogLevel.INFO);
LoggerHandler fileLogger = new FileLogger(LogLevel.DEBUG);
LoggerHandler databaseLogger = new DatabaseLogger(LogLevel.ERROR);
// 构建责任链
consoleLogger.setNext(fileLogger).setNext(databaseLogger);
// 创建日志消息
LogMessage infoLog = new LogMessage(LogLevel.INFO, "这是一条信息日志");
LogMessage debugLog = new LogMessage(LogLevel.DEBUG, "这是一条调试日志");
LogMessage errorLog = new LogMessage(LogLevel.ERROR, "这是一条错误日志");
// 处理日志
System.out.println("=== 处理信息日志 ===");
consoleLogger.log(infoLog);
System.out.println("\n=== 处理调试日志 ===");
consoleLogger.log(debugLog);
System.out.println("\n=== 处理错误日志 ===");
consoleLogger.log(errorLog);
}
}
实际应用示例:Web请求过滤器
下面是一个Web请求过滤器的例子,类似于Java Servlet Filter:
// HTTP请求
class HttpRequest {
private String requestBody;
private Map<String, String> headers;
private String ip;
public HttpRequest(String ip, Map<String, String> headers, String requestBody) {
this.ip = ip;
this.headers = headers;
this.requestBody = requestBody;
}
public String getRequestBody() {
return requestBody;
}
public Map<String, String> getHeaders() {
return headers;
}
public String getIp() {
return ip;
}
}
// HTTP响应
class HttpResponse {
private int statusCode;
private String body;
public HttpResponse() {
this.statusCode = 200;
this.body = "";
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public void setBody(String body) {
this.body = body;
}
@Override
public String toString() {
return "HttpResponse{" +
"statusCode=" + statusCode +
", body='" + body + '\'' +
'}';
}
}
// 过滤器接口
interface Filter {
void setNext(Filter filter);
HttpResponse doFilter(HttpRequest request, HttpResponse response);
}
// 抽象过滤器
abstract class BaseFilter implements Filter {
protected Filter next;
@Override
public void setNext(Filter filter) {
this.next = filter;
}
@Override
public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
// 如果有下一个过滤器,调用它
if (next != null) {
return next.doFilter(request, response);
}
return response;
}
}
// IP黑名单过滤器
class IpBlacklistFilter extends BaseFilter {
private List<String> blacklist = Arrays.asList("192.168.1.1", "10.0.0.1");
@Override
public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
if (blacklist.contains(request.getIp())) {
response.setStatusCode(403);
response.setBody("IP被禁止访问");
return response;
}
return super.doFilter(request, response);
}
}
// 认证过滤器
class AuthenticationFilter extends BaseFilter {
@Override
public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
if (!request.getHeaders().containsKey("Authorization")) {
response.setStatusCode(401);
response.setBody("需要认证");
return response;
}
return super.doFilter(request, response);
}
}
// 内容类型过滤器
class ContentTypeFilter extends BaseFilter {
@Override
public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
if (!request.getHeaders().containsKey("Content-Type") ||
!request.getHeaders().get("Content-Type").equals("application/json")) {
response.setStatusCode(415);
response.setBody("不支持的媒体类型");
return response;
}
return super.doFilter(request, response);
}
}
// 日志过滤器
class LoggingFilter extends BaseFilter {
@Override
public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
System.out.println("请求IP: " + request.getIp());
System.out.println("请求头: " + request.getHeaders());
HttpResponse processedResponse = super.doFilter(request, response);
System.out.println("响应状态码: " + processedResponse.toString());
return processedResponse;
}
}
// Web应用
class WebApplication {
private Filter filterChain;
public WebApplication(Filter filterChain) {
this.filterChain = filterChain;
}
public HttpResponse handleRequest(HttpRequest request) {
HttpResponse response = new HttpResponse();
// 执行过滤器链
response = filterChain.doFilter(request, response);
// 如果请求通过所有过滤器,设置成功响应
if (response.toString().contains("statusCode=200")) {
response.setBody("请求处理成功");
}
return response;
}
}
// 客户端代码
public class WebFilterExample {
public static void main(String[] args) {
// 创建过滤器
Filter loggingFilter = new LoggingFilter();
Filter ipFilter = new IpBlacklistFilter();
Filter authFilter = new AuthenticationFilter();
Filter contentTypeFilter = new ContentTypeFilter();
// 设置过滤器链
loggingFilter.setNext(ipFilter);
ipFilter.setNext(authFilter);
authFilter.setNext(contentTypeFilter);
// 创建Web应用
WebApplication app = new WebApplication(loggingFilter);
// 测试不同请求
Map<String, String> headers1 = new HashMap<>();
HttpRequest request1 = new HttpRequest("192.168.1.1", headers1, "");
Map<String, String> headers2 = new HashMap<>();
HttpRequest request2 = new HttpRequest("192.168.1.2", headers2, "");
Map<String, String> headers3 = new HashMap<>();
headers3.put("Authorization", "Bearer token123");
HttpRequest request3 = new HttpRequest("192.168.1.2", headers3, "");
Map<String, String> headers4 = new HashMap<>();
headers4.put("Authorization", "Bearer token123");
headers4.put("Content-Type", "application/json");
HttpRequest request4 = new HttpRequest("192.168.1.2", headers4, "{\"key\":\"value\"}");
// 处理请求
System.out.println("=== 请求1: 黑名单IP ===");
System.out.println(app.handleRequest(request1));
System.out.println("\n=== 请求2: 未认证 ===");
System.out.println(app.handleRequest(request2));
System.out.println("\n=== 请求3: 缺少Content-Type ===");
System.out.println(app.handleRequest(request3));
System.out.println("\n=== 请求4: 有效请求 ===");
System.out.println(app.handleRequest(request4));
}
}
责任链模式在Java API中的应用
Java API中有多个使用责任链模式的例子:
java.util.logging.Logger:日志记录器采用了责任链模式,消息沿着Logger层次结构传递。
javax.servlet.Filter:Java Servlet中的过滤器链,HTTP请求依次经过一系列过滤器处理。
java.awt.Container#dispatchEvent():事件处理中,事件沿着组件层次结构传递。
责任链模式的优点
降低耦合度:请求发送者与接收者解耦,发送者无需知道谁会处理请求。
增强灵活性:可以动态地添加、删除或重新排序处理者,而不影响客户端代码。
符合单一职责原则:每个处理者只关注自己能处理的请求类型。
符合开闭原则:无需修改现有代码即可添加新的处理者。
可以实现不同的处理方式:请求可以由一个处理者处理或多个处理者部分处理。
责任链模式的缺点
请求可能没有处理者:如果链末尾没有合适的处理者,请求可能未被处理。
性能问题:请求可能要遍历整条链才能找到合适的处理者。
调试困难:请求在链中的行为路径不易跟踪,增加了调试难度。
可能的递归调用:处理者之间的递归调用可能导致栈溢出。
责任链模式与其他模式的比较
责任链 vs 命令模式
- 责任链模式:专注于请求的传递和处理,接收者可能有多个。
- 命令模式:将请求封装为对象,关注请求的发送者和接收者之间的解耦。
责任链 vs 装饰器模式
- 责任链模式:每个处理者决定是否处理请求或传递给下一个处理者。
- 装饰器模式:每个装饰器都会处理请求,然后将其传递给下一个组件。
责任链模式的变体
1. 纯责任链
每个处理者要么完全处理请求,要么将请求完全传递给下一个处理者:
// 纯责任链处理者
interface PureHandler {
boolean handle(Request request);
void setNext(PureHandler handler);
}
2. 带回调的责任链
处理完成后调用回调方法:
// 带回调的处理者
interface CallbackHandler {
void handle(Request request, Callback callback);
}
// 回调接口
interface Callback {
void onSuccess(String result);
void onFailure(String error);
}
最佳实践和注意事项
合理设置处理顺序:将常用或简单的处理者放在链的前面,提高效率。
设置默认处理者:确保链末尾有默认处理者,避免请求未处理。
警惕处理循环:确保责任链中不会出现循环引用。
避免过长的责任链:过长的链会影响性能和可维护性。
考虑链的动态性:在某些情况下,可能需要动态修改责任链。
明确终止条件:每个处理者应明确何时停止处理,何时传递请求。
总结
责任链模式是一种强大的行为设计模式,它允许多个对象处理同一个请求,而发送者无需知道具体的处理者。通过将对象连成一条链,并沿着链传递请求,直到有对象能够处理它为止,责任链模式提供了一种灵活且松耦合的解决方案。
这种模式在需要按特定顺序处理请求,或者不确定由哪个对象处理请求的场景中非常有用。它广泛应用于日志记录、错误处理、请求过滤、事件处理等多种场景。
虽然责任链模式有可能导致请求未被处理或性能问题,但通过合理设计和使用,这些缺点是可以避免的。在复杂的系统中,责任链模式是实现灵活处理流程的有效工具。