设计模式——责任链模式

566 阅读3分钟

1. 责任链模式概述

责任链模式为请求创建了一个接收者对象的链。这种模式基于请求的类型,对请求的发送者和接收者进行解耦。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

(1) 适用情况

在处理消息时需要过滤很多次的时候,比如filter的实现。

(2) 优点

可以将请求的发送者和请求的处理者进行解耦,发送者只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递。

(3) 缺点

对责任链的顺序有要求,可能会由于顺序错误导致非预期的问题。责任链上有些节点可能需要处理的情况较少,请求每次经过它会造成不必要的性能影响。

2. 责任链模式实例

使用过log4j的同学应该都知道,需要配置默认的日志打印级别。比该级别优先级更高的日志信息都会打印出来,而更低的则不会。
例如,在log4j2中的日志优先级从高到低为:OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
如果当前设置的打印级别为info,则只会打印INFO、WARN、ERROR等等。

这里使用责任链模式,来模拟简单的日志打印过程。

(1) 创建Logger的抽象类

public abstract class Logger {
    public static final int ERROR = 1;
    public static final int DEBUG = 2;
    public static final int INFO = 3;

    // 责任链中的下一跳
    private Logger nextLogger;

    // 日志信息级别
    protected int level;

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

    public void logMessage(int level, String message) {
        // 优先级更高的日志都需要记录
        if (level <= this.level) {
            write(message);
        }
        // 如果责任链没有结束,则调用下一跳
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    protected abstract void write(String message);
}

(2) 实现不同级别的日志处理类

public class InfoLogger extends Logger {
    public InfoLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Info::logger: " + message);
    }
}
public class DebugLogger extends Logger {
    public DebugLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Debug::logger: " + message);
    }
}
public class ErrorLogger extends Logger {
    public ErrorLogger(int level) {
        this.level = level;
    }

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

(3) 打印不同级别的日志信息

public class ChainDemo {
    public static void main(String[] args) {
        Logger chainOfLoggers = getChainOfLoggers();
        // 打印INFO日志
        chainOfLoggers.logMessage(Logger.INFO, "INFO日志。");
        // 打印DEBUG日志
        chainOfLoggers.logMessage(Logger.DEBUG, "DEBUG日志。");
        // 打印ERROR日志
        chainOfLoggers.logMessage(Logger.ERROR, "ERROR日志。");

    }

    private static Logger getChainOfLoggers() {
        Logger infoLogger = new InfoLogger(Logger.INFO);
        Logger debugLogger = new DebugLogger(Logger.DEBUG);
        Logger errorLogger = new ErrorLogger(Logger.ERROR);

        // 按照优先级从高到低
        errorLogger.setNextLogger(debugLogger);
        debugLogger.setNextLogger(infoLogger);

        return errorLogger;
    }
}

运行结果:
image.png

3. 一些思考

从运行结果中可以看出,INFO日志只在InfoLogger中打印,DEBUG日志在DebugLogger和InfoLogger中都打印了,ERROR日志在三个日志处理类中都打印了,确实符合优先级的要求。

注意到getChainOfLoggers方法,只返回了errorLogger,即只返回了责任链的首部而已,确实将请求的发送者和处理者解耦了。

参考引用

责任链模式:www.runoob.com/design-patt…