# 责任链模式

# 概念

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心思想是将请求的发送者和接收者解耦,允许多个对象按顺序处理请求。请求沿处理链传递,直到被某个处理者处理或链结束。

# 作用

1.解耦:发送者无需知道具体由哪个处理者处理请求,降低系统耦合度。

2.动态组合:可灵活调整处理链的顺序或增减处理者,适应业务变化。

3.单一职责:每个处理者专注自己的处理逻辑,符合单一职责原则。

# 场景

1.多级日志处理:根据日志级别选择不同输出方式(如控制台、文件、邮件)。

2.权限校验:依次检查用户权限(如登录态、角色、资源权限)。

3.请求过滤:Web 框架中的中间件链(如身份验证、缓存、压缩)。

# 举例

以下是使用责任链模式实现多级日志处理的Java代码示例:

// 抽象日志处理器
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

# 反例

如果不使用责任链模式,通常会通过条件分支硬编码处理逻辑,导致代码耦合度高且难以扩展:

// 硬编码条件判断的日志处理
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.违反开闭原则:新增日志处理器需修改log方法,破坏封装性。

2.代码臃肿:条件分支随处理者增多变得复杂,难以维护。

3.复用性差:处理流程固化,无法动态调整或复用。

# 原理

责任链模式通过以下机制实现解耦和动态组合:

1.链式传递:每个处理者持有下一个处理者的引用,形成链式结构。

2.自处理判断:处理者根据自身逻辑决定是否处理请求或继续传递。

3.动态配置:通过修改链的顺序或增减节点,灵活控制处理流程。

# 缺点

1.性能损耗:长链可能导致遍历开销,需权衡性能与灵活性。

2.请求遗漏:若链未正确配置,请求可能未被处理,需完善终止条件。

总结

责任链模式通过链式传递和动态组合,解决了条件分支的硬编码问题,尤其适用于多级处理场景。其核心价值在于将处理逻辑分散到独立类中,提升代码的可维护性和扩展性,但需注意避免过度设计导致的性能问题。



微信公众号

QQ交流群
原创网站开发,偏差难以避免。

如若发现错误,诚心感谢反馈。

愿你倾心相念,愿你学有所成。

愿你朝华相顾,愿你前程似锦。