概念
责任链模式将请求的发送者和接收者解耦,允许多个对象都有机会处理请求。请求沿处理链传递,直到被处理或链结束。
作用
1.解耦:发送者无需知道具体由哪个处理者处理请求。
2.动态组合:可灵活调整处理链的顺序或增减处理者。
3.单一职责:每个处理者专注自己的处理逻辑。
场景
1.多级日志处理:根据日志级别选择不同输出方式。
2.权限校验:依次检查用户权限(如登录态、角色、资源权限)。
3.请求过滤:Web 框架中的中间件链(如身份验证、缓存、压缩)。
示例
// 抽象日志处理器
public abstract class AbstractLogger {
public static int DEBUG = 1;
public static int INFO = 2;
public static int ERROR = 3;
protected int level;
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message) {
if (this.level <= level) {
write(message);
}
if (nextLogger != null) {
nextLogger.logMessage(level, message);
}
}
protected abstract void write(String message);
}
// 控制台日志(处理 DEBUG 及以上)
class ConsoleLogger extends AbstractLogger {
public ConsoleLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Console: " + message);
}
}
// 文件日志(处理 INFO 及以上)
class FileLogger extends AbstractLogger {
public FileLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("File: " + message);
}
}
// 邮件日志(处理 ERROR)
class EmailLogger extends AbstractLogger {
public EmailLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Email: " + message);
}
}
// 构建责任链
public class ChainDemo {
public static void main(String[] args) {
// 构建处理链:Console -> File -> Email
AbstractLogger console = new ConsoleLogger(AbstractLogger.DEBUG);
AbstractLogger file = new FileLogger(AbstractLogger.INFO);
AbstractLogger email = new EmailLogger(AbstractLogger.ERROR);
console.setNextLogger(file);
file.setNextLogger(email);
// 触发请求
console.logMessage(AbstractLogger.DEBUG, "Debug message"); // 仅 Console 处理
console.logMessage(AbstractLogger.INFO, "Info message"); // Console 和 File 处理
console.logMessage(AbstractLogger.ERROR, "Error message");// 三者均处理
}
}
Console: Debug message
Console: Info message
File: Info message
Console: Error message
File: Error message
Email: Error message
优点和缺点
优点
1.解耦性:请求发送者无需关注处理细节。
2.扩展性:新增处理者只需修改链结构,无需改动现有代码。
3.灵活性:动态调整处理顺序或禁用某些处理者。
缺点
1.性能损耗:长链可能导致遍历开销。
2.请求遗漏:若链未正确配置,请求可能未被处理。
无责任链模式的实现方式
若不用责任链模式,通常需通过条件分支硬编码处理逻辑,导致耦合:
// 硬编码条件判断的日志处理
public class LoggerWithoutChain {
public void log(int level, String message) {
if (level >= AbstractLogger.DEBUG) {
System.out.println("Console: " + message);
}
if (level >= AbstractLogger.INFO) {
System.out.println("File: " + message);
}
if (level >= AbstractLogger.ERROR) {
System.out.println("Email: " + message);
}
}
}
问题
1.违反开闭原则:新增日志处理器需修改方法。
2.代码臃肿:条件分支随处理者增多变得复杂。
3.复用性差:难以动态调整处理流程。
总结
责任链模式通过链式传递和动态组合解决了条件分支的硬编码问题,尤其适用于需要多级处理的场景。其核心价值在于将处理逻辑分散到独立的类中,提升代码的可维护性和扩展性。