各位宝子们,今天我们来聊一个设计模式界的"甩锅高手"——责任链模式! 还在为请求处理逻辑耦合度高而头疼吗?还在为条件判断嵌套太深而烦恼吗?责任链模式来拯救你啦!
责任链模式是设计模式家族中的"接力赛选手",它能帮我们优雅地处理请求,让代码更加灵活、可维护。今天就带大家彻底搞懂这个"看似简单,实则强大"的设计模式!
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。就像公司里的请假流程一样,从直属领导到部门经理再到总经理,请求沿着责任链传递!
想象一下这些场景:
这些场景有什么共同点?它们都涉及到请求处理的灵活性和解耦。责任链模式就是为这些场景量身定制的!
责任链模式包含以下几个角色:
// 抽象处理者
public abstract class Handler {
protected Handler successor; // 后继处理者
// 设置后继处理者
public void setSuccessor(Handler successor) {
this.successor = successor;
}
// 处理请求的抽象方法
public abstract void handleRequest(Request request);
}
// 具体处理者A
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(Request request) {
if (canHandle(request)) {
System.out.println("处理者A处理了请求: " + request.getContent());
} else if (successor != null) {
// 转发给下一个处理者
successor.handleRequest(request);
} else {
System.out.println("没有人能处理这个请求");
}
}
// 判断是否能处理请求
private boolean canHandle(Request request) {
// 根据请求内容判断是否能处理
return "TypeA".equals(request.getType());
}
}
// 具体处理者B
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(Request request) {
if (canHandle(request)) {
System.out.println("处理者B处理了请求: " + request.getContent());
} else if (successor != null) {
// 转发给下一个处理者
successor.handleRequest(request);
} else {
System.out.println("没有人能处理这个请求");
}
}
// 判断是否能处理请求
private boolean canHandle(Request request) {
// 根据请求内容判断是否能处理
return "TypeB".equals(request.getType());
}
}
// 请求类
public class Request {
private String type;
private String content;
public Request(String type, String content) {
this.type = type;
this.content = content;
}
public String getType() {
return type;
}
public String getContent() {
return content;
}
}
// 客户端代码
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
// 构建责任链
handlerA.setSuccessor(handlerB);
// 发送请求
Request requestA = new Request("TypeA", "请求A");
Request requestB = new Request("TypeB", "请求B");
Request requestC = new Request("TypeC", "请求C");
handlerA.handleRequest(requestA); // 处理者A处理了请求: 请求A
handlerA.handleRequest(requestB); // 处理者B处理了请求: 请求B
handlerA.handleRequest(requestC); // 没有人能处理这个请求
看到了吗?我们通过构建一条处理链,让请求沿着链条传递,直到找到合适的处理者!这就像公司里的审批流程,每个领导只处理自己权限范围内的请求,超出权限就往上传递!
让我们实现一个日志记录系统,根据日志级别(DEBUG、INFO、ERROR)决定由谁来处理:
// 日志级别枚举
public enum LogLevel {
DEBUG(1), INFO(2), ERROR(3);
private int level;
LogLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
// 日志消息类
public class LogMessage {
private String message;
private LogLevel level;
public LogMessage(String message, LogLevel level) {
this.message = message;
this.level = level;
}
public String getMessage() {
return message;
}
public LogLevel getLevel() {
return level;
}
}
// 抽象日志处理器
public abstract class LogHandler {
protected LogLevel level;
protected LogHandler nextHandler;
public LogHandler(LogLevel level) {
this.level = level;
}
public LogHandler setNext(LogHandler nextHandler) {
this.nextHandler = nextHandler;
return nextHandler; // 返回下一个处理器,方便链式调用
}
public void logMessage(LogMessage logMessage) {
if (logMessage.getLevel().getLevel() >= this.level.getLevel()) {
write(logMessage);
}
if (nextHandler != null) {
nextHandler.logMessage(logMessage);
}
}
protected abstract void write(LogMessage logMessage);
}
// 控制台日志处理器(处理DEBUG级别)
public class ConsoleLogHandler extends LogHandler {
public ConsoleLogHandler() {
super(LogLevel.DEBUG);
}
@Override
protected void write(LogMessage logMessage) {
System.out.println("控制台日志: [" + logMessage.getLevel() + "] " + logMessage.getMessage());
}
}
// 文件日志处理器(处理INFO级别)
public class FileLogHandler extends LogHandler {
public FileLogHandler() {
super(LogLevel.INFO);
}
@Override
protected void write(LogMessage logMessage) {
System.out.println("文件日志: [" + logMessage.getLevel() + "] " + logMessage.getMessage());
}
}
// 邮件日志处理器(处理ERROR级别)
public class EmailLogHandler extends LogHandler {
public EmailLogHandler() {
super(LogLevel.ERROR);
}
@Override
protected void write(LogMessage logMessage) {
System.out.println("邮件日志: [" + logMessage.getLevel() + "] " + logMessage.getMessage());
}
}
// 客户端代码
LogHandler consoleLogger = new ConsoleLogHandler();
LogHandler fileLogger = new FileLogHandler();
LogHandler emailLogger = new EmailLogHandler();
// 构建责任链
consoleLogger.setNext(fileLogger).setNext(emailLogger);
// 发送日志消息
consoleLogger.logMessage(new LogMessage("这是一条调试信息", LogLevel.DEBUG));
// 输出:控制台日志: [DEBUG] 这是一条调试信息
consoleLogger.logMessage(new LogMessage("这是一条普通信息", LogLevel.INFO));
// 输出:
// 控制台日志: [INFO] 这是一条普通信息
// 文件日志: [INFO] 这是一条普通信息
consoleLogger.logMessage(new LogMessage("这是一条错误信息", LogLevel.ERROR));
// 输出:
// 控制台日志: [ERROR] 这是一条错误信息
// 文件日志: [ERROR] 这是一条错误信息
// 邮件日志: [ERROR] 这是一条错误信息
这个例子展示了责任链模式的强大之处!我们可以根据日志级别,让不同的处理器处理日志,而且可以同时由多个处理器处理同一条日志。这种灵活性是责任链模式的一大特点!
在Web应用中,责任链模式经常用于实现过滤器或拦截器:
// HTTP请求类
public class HttpRequest {
private String url;
private String method;
private Map<String, String> headers;
// 构造方法、getter和setter省略...
}
// HTTP响应类
public class HttpResponse {
private int statusCode;
private Map<String, String> headers;
private String body;
// 构造方法、getter和setter省略...
}
// 过滤器接口
public interface Filter {
void doFilter(HttpRequest request, HttpResponse response, FilterChain chain);
}
// 过滤器链
public class FilterChain {
private List<Filter> filters = new ArrayList<>();
private int index = 0;
public FilterChain addFilter(Filter filter) {
filters.add(filter);
return this;
}
public void doFilter(HttpRequest request, HttpResponse response) {
if (index < filters.size()) {
Filter filter = filters.get(index);
index++;
filter.doFilter(request, response, this);
}
}
}
// 认证过滤器
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(HttpRequest request, HttpResponse response, FilterChain chain) {
// 检查认证信息
String authHeader = request.getHeaders().get("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
response.setStatusCode(401);
response.setBody("未授权访问");
return; // 不继续传递请求
}
System.out.println("认证过滤器:认证成功");
chain.doFilter(request, response); // 继续传递请求
}
}
// 日志过滤器
public class LoggingFilter implements Filter {
@Override
public void doFilter(HttpRequest request, HttpResponse response, FilterChain chain) {
System.out.println("日志过滤器:请求 " + request.getMethod() + " " + request.getUrl());
chain.doFilter(request, response); // 继续传递请求
System.out.println("日志过滤器:响应状态码 " + response.getStatusCode());
}
}
// 客户端代码
HttpRequest request = new HttpRequest();
request.setUrl("/api/users");
request.setMethod("GET");
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer token123");
request.setHeaders(headers);
HttpResponse response = new HttpResponse();
FilterChain chain = new FilterChain();
chain.addFilter(new LoggingFilter())
.addFilter(new AuthenticationFilter());
chain.doFilter(request, response);
这个例子展示了Web应用中常见的过滤器链实现,每个过滤器负责特定的功能,如日志记录、认证、授权等。这种实现方式使得我们可以灵活地添加、删除或重新排序过滤器,而不影响核心业务逻辑!
Java的Servlet规范中的Filter就是责任链模式的应用:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// 前置处理
// 传递给下一个过滤器
chain.doFilter(request, response);
// 后置处理
}
Spring MVC中的HandlerInterceptor也是责任链模式的应用:
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 前置处理
return true; // 返回true才会继续传递请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
// 处理完成后的操作
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 视图渲染完成后的操作
}
}
Java的异常处理机制也可以看作是责任链模式的一种应用:
try {
// 可能抛出异常的代码
} catch (IllegalArgumentException e) {
// 处理IllegalArgumentException
} catch (RuntimeException e) {
// 处理RuntimeException
} catch (Exception e) {
// 处理Exception
} finally {
// 清理资源
}
异常会沿着catch块链传递,直到找到匹配的异常类型。这与责任链模式的思想非常相似!
责任链模式是一种非常实用的设计模式,它让我们可以将请求的发送者和接收者解耦,使得多个对象都有机会处理请求。它通过构建处理者链,让请求沿着链传递,直到找到合适的处理者。
在实际开发中,当你面对复杂的条件判断逻辑,或者需要灵活地处理请求时,责任链模式是一个非常好的选择!记住,好的设计模式就像好的工具一样,用在对的地方才能发挥最大的作用!
下次当你写出一堆if-else判断逻辑时,不妨问问自己:“我是应该继续堆砌条件判断,还是应该使用责任链模式呢?” 如果你需要灵活地处理请求,那么责任链模式可能是更好的选择!
希望这篇文章对你理解责任链模式有所帮助!如果有任何问题,欢迎在评论区留言讨论!