责任链模式:构建一条责任链去处理不同级别的日志信息

概要

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,在有多个对象(处理者)都可以接收请求的情况下,允许你将多个对象连接成一条处理链,请求沿着处理链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。这种方式在处理一系列请求方面,提供了更灵活、可扩展的解决方案,同时避免了请求发送者和接收者之间的紧密耦合。

chain01

责任链模式的角色

  • 抽象处理者(Handler):一般为抽象类,需要包含一个成员变量来存储指向链上后继节点的引用,同时包含设置后继节点的方法以及处理请求的方法。在处理方法中,需要判断是否自行处理本次请求,还是将请求发送给后继者。
  • 具体处理者(Concrete Handler):实现抽象处理者。
  • 客户类:构建处理链,并向链头的具体处理者提交请求,它不关心处理细节和请求的传递过程。

优点

  • 降低耦合度:将请求发送者和接收者之间进行解耦,降低系统耦合度。
  • 提高系统灵活性和扩展性:可以动态地组合责任链,增加或删除处理对象,灵活调整处理对象的顺序。
  • 符合开闭原则:可以在不修改现有系统的基础上,新增新的处理对象。

缺点

  • 性能问题:请求可能需要沿着链经过多个处理对象才能被处理,这可能导致性能问题。
  • 不保证请求一定被处理:如果没有合适的处理对象处理请求,请求可能会一直传递到链的末尾而未被处理。

适用场景

  • 当有多个对象可以处理同一个请求,具体哪个对象处理请求由运行时刻自动确定,可以使用责任链模式。
  • 当需要在运行时动态地添加或删除处理对象,灵活组合和调整处理流程时,可以使用责任链模式。
  • 当需要避免请求发送者和接收者之间的耦合,可以使用责任链模式。
  • 当需要在不同的处理对象之间共享数据时,可以使用责任链模式。

实现案例

我们都知道在log4j2中,日志级别由低到高可分为8个级别:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF,每个级别只会打印当前级别和以上级别的消息。我们用 INFO、WARN 、ERROR三个日志级别举例,如果日志级别为INFO,则会打印INFO、WARN 、ERROR三个级别的信息,如果日志级别为ERROR,则只会打印ERROR级别的信息。现在我们模拟这三个级别的日志输出控制器,构建一条处理链去处理不同级别的日志信息。

步骤1:抽象处理者AbstractLogger

public abstract class AbstractLogger {
    public static int INFO = 1;
    public static int WARN = 2;
    public static int ERROR = 3;

    protected int level;

    //责任链中的下一个元素
    protected AbstractLogger nextHandler;

    public void setNext(AbstractLogger nextHandler){
        this.nextHandler = nextHandler;
    }

    public void handleMessage(int level, String message){
        //消息级别高于或等于所设置级别就打印消息
        if(level >= this.level){
            write(message);
        }
        //将请求传递给后继者
        if(nextHandler !=null){
            nextHandler.handleMessage(level, message);
        }
    }
    abstract protected void write(String message);

}

步骤2:分别实现三个具体处理者ErrorConsole、WarnConsole、InfoConsole

public class ErrorConsole extends AbstractLogger {

    public ErrorConsole(){
        //日志级别设为ERROR
        this.level = AbstractLogger.ERROR;
    }

    @Override
    protected void write(String message) {
        System.out.println("[Error Console] - " + message);
    }
}
public class WarnConsole extends AbstractLogger {

    public WarnConsole(){
        //日志级别设为WARN
        this.level = AbstractLogger.WARN;
    }

    @Override
    protected void write(String message) {
        System.out.println("[Warn Console] - " + message);
    }
}
public class InfoConsole extends AbstractLogger {

    public InfoConsole(){
         //日志级别设为INFO
        this.level = AbstractLogger.INFO;
    }

    @Override
    protected void write(String message) {
        System.out.println("[Info Console] - " + message);
    }
}

步骤3:客户端构建责任链,并分别处理不同级别的日志信息

public class Client {
    public static void main(String[] args) {
        //构建责任链,errorConsole为链头,warnConsole和infoConsole为后继节点
        AbstractLogger errorConsole=new ErrorConsole();
        AbstractLogger warnConsole=new WarnConsole();
        AbstractLogger infoConsole=new InfoConsole();
        errorConsole.setNext(warnConsole);
        warnConsole.setNext(infoConsole);

        //统一由责任链的链头接收请求,分别测试三种类型的信息
        errorConsole.handleMessage(AbstractLogger.INFO, "INFO:正常信息");
        System.out.println();

        errorConsole.handleMessage(AbstractLogger.WARN, "WARN:警告信息");
        System.out.println();

        errorConsole.handleMessage(AbstractLogger.ERROR, "ERROR:错误消息");

    }
}

测试结果

image-20230614161118052

由上述代码可知,我们构建了一条责任链去处理日志信息:errorConsole -> warnConsole -> infoConsole,当输入INFO类型的信息时,首先进入errorConsole ,没有进行输出处理,随后进入warnConsole ,也没有进行输出处理,最后进入infoConsole,才进行了输出处理。同理,当输入WARN信息时,后两个处理对象都进行了处理,当输入ERROR信息时,三个处理对象都进行了输出处理。这正好符合我们前面说的,每个日志级别只会打印当前级别和以上级别的消息

总结

通过本篇文章的学习,我们可以看出,当我们有一系列请求存在多个处理对象时,可以将这些处理对象构建成一条处理链,让请求沿着处理链依次进行传递处理,这就是责任链模式。它可以动态地组合处理链,新增和删除处理对象,同时可以随意编排处理对象的顺序,大大提升系统的灵活性和可扩展性,降低系统耦合度。当然,这种模式也存在一定的弊端,比如责任链过长带来处理的延时性,同时不能保证请求一定能得到处理,在日常开发过程中需要结合实际场景进行权衡。

希望这篇文章对你的学习有所帮助,在此感谢你的阅读!

1711edbd2bd444b1b647e09c2c3aff0d

评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值