Bootstrap

【设计模式】责任链 So easy

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。这些对象通过形成一条链来传递请求,直到有一个对象处理它为止。本文将详细介绍责任链模式的概念、结构、实现方法及其优缺点。

责任链模式的结构

责任链模式主要包含以下几个角色:

  1. 抽象处理者(Handler):定义一个处理请求的接口,并实现后续链条的引用。
  2. 具体处理者(ConcreteHandler):实现抽象处理者接口,处理它所负责的请求;可以访问它的后继者,如果可以处理请求则处理,否则将请求传递给后继者。
  3. 客户端(Client):向链上的具体处理者对象提交请求。

责任链模式的类图

在这里插入图片描述

责任链模式的实现

以下是使用Java实现责任链模式的详细代码示例。

1. 定义抽象处理者接口

public abstract class Handler {
    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(int request);
}

2. 实现具体处理者类

public class ConcreteHandler1 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 0 && request < 10) {
            System.out.println("ConcreteHandler1 handled request: " + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

public class ConcreteHandler2 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 10 && request < 20) {
            System.out.println("ConcreteHandler2 handled request: " + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

public class ConcreteHandler3 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 20 && request < 30) {
            System.out.println("ConcreteHandler3 handled request: " + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

3. 客户端代码

public class ChainOfResponsibilityPatternTest {
    public static void main(String[] args) {
        // 创建处理者
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        Handler handler3 = new ConcreteHandler3();

        // 设置责任链
        handler1.setSuccessor(handler2);
        handler2.setSuccessor(handler3);

        // 创建请求
        int[] requests = {5, 14, 22, 18, 3, 27};

        // 处理请求
        for (int request : requests) {
            handler1.handleRequest(request);
        }
    }
}

运行结果:

ConcreteHandler1 handled request: 5
ConcreteHandler2 handled request: 14
ConcreteHandler3 handled request: 22
ConcreteHandler2 handled request: 18
ConcreteHandler1 handled request: 3
ConcreteHandler3 handled request: 27

责任链模式的优缺点

优点

  1. 降低耦合度:客户端不需要知道具体处理者的存在,处理者之间的调用顺序是隐式的。
  2. 增强灵活性:可以通过动态组合职责链来改变链中的处理者的职责。
  3. 增加新的请求处理类:增加新的请求处理类时无需修改现有代码,只需在链中增加一个新的具体处理者即可。

缺点

  1. 不保证请求一定被处理:如果链中的处理者都没有处理请求,客户端并不会知道请求没有被处理。
  2. 影响性能:如果链过长,处理请求时可能会涉及多个处理者,影响系统性能。
  3. 调试复杂:由于链中的处理者是动态组合的,调试时可能不容易找到问题所在。

应用场景

责任链模式适用于以下场景:

  1. 多个对象可以处理同一个请求:但具体哪个对象处理该请求在运行时自动确定。
  2. 需要动态指定处理对象:客户端可以动态指定链中的处理者。
  3. 请求处理者需要灵活应对变化:可以通过动态组合处理者链来应对变化。

实例应用

以下是一个实例应用,展示如何使用责任链模式来实现日志记录器,支持不同级别的日志记录。

1. 定义日志级别枚举

public enum LogLevel {
    INFO,
    DEBUG,
    ERROR
}

2. 定义抽象日志处理者接口

public abstract class Logger {
    protected LogLevel logLevel;
    protected Logger nextLogger;

    public void setNextLogger(Logger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void logMessage(LogLevel level, String message) {
        if (this.logLevel == level) {
            write(message);
        } else if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    protected abstract void write(String message);
}

3. 实现具体日志处理者类

public class ConsoleLogger extends Logger {
    public ConsoleLogger(LogLevel logLevel) {
        this.logLevel = logLevel;
    }

    @Override
    protected void write(String message) {
        System.out.println("Console Logger: " + message);
    }
}

public class FileLogger extends Logger {
    public FileLogger(LogLevel logLevel) {
        this.logLevel = logLevel;
    }

    @Override
    protected void write(String message) {
        System.out.println("File Logger: " + message);
    }
}

public class ErrorLogger extends Logger {
    public ErrorLogger(LogLevel logLevel) {
        this.logLevel = logLevel;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error Logger: " + message);
    }
}

4. 客户端代码

public class ChainOfResponsibilityLoggerTest {
    private static Logger getChainOfLoggers() {
        Logger errorLogger = new ErrorLogger(LogLevel.ERROR);
        Logger fileLogger = new FileLogger(LogLevel.DEBUG);
        Logger consoleLogger = new ConsoleLogger(LogLevel.INFO);

        consoleLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(errorLogger);

        return consoleLogger;
    }

    public static void main(String[] args) {
        Logger loggerChain = getChainOfLoggers();

        loggerChain.logMessage(LogLevel.INFO, "This is an information.");
        loggerChain.logMessage(LogLevel.DEBUG, "This is a debug level information.");
        loggerChain.logMessage(LogLevel.ERROR, "This is an error information.");
    }
}

运行结果:

Console Logger: This is an information.
File Logger: This is a debug level information.
Error Logger: This is an error information.

总结

责任链模式是一种常用的行为型设计模式,通过将请求沿着一条链传递,使得多个对象都有机会处理请求。本文详细介绍了责任链模式的概念、结构、实现方法及其优缺点,并通过实例应用展示了如何使用责任链模式实现不同级别的日志记录器。希望本文能够帮助你更好地理解和应用责任链模式,提高代码的灵活性和可维护性。

;