定义理解
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将多个对象连接成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。这种模式的主要目的是避免请求发送者与多个接收者之间的耦合关系,将请求的发送者和接收者解耦。
责任链模式使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
特点:
- 链上的每个对象都有机会处理请求。
- 链上的每个对象都持有下一个要处理对象的引用。
- 如果链上的某个对象无法处理当前请求,那么它会把相同的请求传给下一个对象。
优点
- 解耦:降低了请求发送者和接收者之间的耦合度。
- 链路结构灵活:可以通过改变链路结构动态地新增或删减责任。
- 易扩展:可以根据需要增加新的请求处理类,满足开闭原则。
- 责任分担:每个类只需要处理自己该处理的工作,符合类的单一职责原则。
缺点
- 性能问题:如果责任链太长或者处理时间过长,会影响整体性能。
- 循环引用:如果节点对象存在循环引用时,会造成死循环,导致系统崩溃。
实现方式
- 抽象处理者(Handler)角色:定义一个处理请求的接口,持有下一个处理类的引用。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的方法,判断能否处理本次请求,否则将请求传给下一个处理者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
应用场景
责任链模式适用于以下场景:
- 过滤器链:在Web开发中,实现过滤器链,如Spring框架中的FilterChain。
- 日志记录器:在日志系统中,将日志记录器组成一条链,实现多种日志记录方式的灵活组合。
- 异常处理器:在应用程序中,实现异常处理器的链式调用,灵活处理各种异常情况。
- 授权认证:在系统中,实现授权认证的链式调用,控制不同用户对系统的访问权限。
日志记录器代码实例
abstract class Logger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
// 责任链中的下一个元素
protected Logger nextLogger;
public void setNextLogger(Logger nextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message) {
if (this.level <= level) {
write(message);
}
if (nextLogger != null) {
nextLogger.logMessage(level, message);
}
}
abstract protected void write(String message);
}
class ConsoleLogger extends Logger {
public ConsoleLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Standard Console::Logger: " + message);
}
}
class ErrorLogger extends Logger {
public ErrorLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " + message);
}
}
class FileLogger extends Logger {
public FileLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("File::Logger: " + message);
}
}
public class ChainPatternDemo {
private static Logger getChainOfLoggers() {
Logger errorLogger = new ErrorLogger(Logger.ERROR);
Logger fileLogger = new FileLogger(Logger.DEBUG);
Logger consoleLogger = new ConsoleLogger(Logger.INFO);
errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);
return errorLogger;
}
public static void main(String[] args) {
Logger loggerChain = getChainOfLoggers();
loggerChain.logMessage(Logger.INFO, "INFO 级别");
loggerChain.logMessage(Logger.DEBUG, " Debug 级别");
loggerChain.logMessage(Logger.ERROR, "Error 级别");
}
}
Logger 类是抽象处理者,它定义了日志的级别、日志消息的处理逻辑(logMessage 方法)以及日志的抽象写入方法(write 方法,这是一个抽象方法,需要在具体处理者中实现)。它还包含了指向下一个处理者的引用(nextLogger)和设置下一个处理者的方法(setNextLogger)。
ConsoleLogger、ErrorLogger 和 FileLogger 是具体处理者,它们继承了 Logger 并实现了 write 方法来定义如何将日志消息写入到不同的目标(控制台、错误控制台、文件)。这些类还接收一个日志级别作为构造函数参数,以确定它们将处理哪些级别的日志消息。
ChainPatternDemo 类是客户端,它负责构建责任链并触发日志消息的传递。getChainOfLoggers 方法创建了三个具体的日志记录器实例,并将它们链接在一起,形成了一个责任链。然后,在 main 方法中,它使用这个责任链来记录不同级别的日志消息。
在 logMessage 方法中,当前日志记录器首先检查消息的级别是否大于或等于其自己的级别。如果是,则通过调用 write 方法处理消息。然后,无论是否处理了消息,它都会将消息传递给链中的下一个日志记录器(如果存在)。这种机制确保了即使某个日志记录器不处理某个级别的消息,其他链中的日志记录器也可能处理它。