【设计模式】-10责任链模式

1.什么是责任链模式?

责任链模式(Chain of Responsibility Pattern):责任链模式就是将请求的接收者对象连成一条链,然后在这一条链上传递请求,直到有个一接收者处理这个请求。通过这样一种方式,避免了请求者和接收者之间的耦合。

说人话: 举个例子,小张来到政府办事大厅办营业执照,可以把小张办营业执照理解为一条请求,政府的办事人员理解为请求的处理者.

由于近年来政府办事效率的提升,小张只需要发起办理执照这条请求,接下来由前台柜员去处理,处理的过程中柜员发现自己不能直接通过,还要上级审核,于是他把请求呈递给他的上司,他的上司看完后觉得自己不能做决定,还需要消防人员去实地检验,最终消防人员验收觉得没问题,于是就把营业执照颁给了小张.

在上述过程中其实小张仅仅只需要发出请求,至于请求是如何被处理的他并不需要关心,这就大大降低了请求者和接受者之间的耦合,请求的处理类似一条链,请求在这条链上传递,最终总有一个人能够处理这条请求,我们称之为责任链模式,这种设计模式在tomcat的filter,mybatis里都有涉及,在文末我会有介绍,接下来先拿最简单的例子入手,毕竟重在理解.

 

2.为什么要使用责任链模式?

因为可以让你的代码变得逼格满满啊,错了,其实最重要还是:

①将请求者和接收者解耦,各模块功能界限清晰,互不影响.

②更好的可扩展性和灵活性,增加新的接收者变得非常容易.

③简化了对象,使对象不需要清楚链的结构,提高了代码的可读性,便于代码的维护.

 

3.适用场景

 ①有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定

 ②在不明确指定接收者的情况下,向多个对象中的一个提交一个请求

 ③可动态指定一组对象处理请求

 

4.实现

这里我拿一个大家比较熟悉的例子来写demo,java有很多日志框架,并且几乎都是支持配置的,你启动的日志优先级不同,显示的日志信息也不同,下面我们就来模拟一下,分别启动debug,info,error级别的日志,在控制台看日志,正常的话应该是debug级别显示的日志最为详细,error显示的日志信息最少.

对于日志的处理,请求实际上只是告诉接收者我当前使用那种级别的日志,至于这个日志最终由那个类来处理,它并不需要关心,请求会沿着这条责任链传递,直到找到能够处理它的类为止.

在正式写代码之前,我觉得有必要梳理下责任链模式的结构,先看下面三张图,分别是tomcat的filter,mybatis的plugin,基于责任链模式实现的handler,有没有发现实际上是千篇一律的,责任链模式主要就是由请求的发起者和处理者构成,处理者一般是多个,构成一条链.

      图1

       图2

     图3

 

弄清了结构之后,下面就动手开发一套沙雕版的日志框架...

这套日志框架里,有一个抽象的爸爸Logger,他有三个儿子,以后可能会生出更多个...不影响我们写代码.三个儿子分别是InfoLog,ErroLog,DebugLog,他们都继承了爸爸Logger,ResponsibilityPatternTest模拟请求的发起者.

代码比较简单,爸爸Logger存放了优先级和责任链中的下一个元素:


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

    protected int level;
    protected Logger nextLogger;

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

    protected abstract void write(String msg);

    public void logMessage(int level, String msg) {
        if (this.level >= level) {
            write(msg);
        }
        if (nextLogger != null) {
            nextLogger.logMessage(level, msg);
        }
    }
}

儿子们分别实现了父类中的抽象方法write(),并在构造器中指定了优先级的参数:

public class DebugLog extends Logger {
    public DebugLog(int level) {
        super.level = level;
    }

    @Override
    protected void write(String msg) {
        System.out.println("=========>DebugLog:" + msg);
    }
}

public class InfoLog extends Logger {
    public InfoLog(int level) {
        super.level = level;
    }

    @Override
    protected void write(String msg) {
        System.out.println("=========>InfoLog:" + msg);
    }
}

public class ErrorLog extends Logger {
    public ErrorLog(int level) {
        super.level = level;
    }

    @Override
    protected void write(String msg) {
        System.out.println("=========>ErrorLog:" + msg);
    }
}

测试类里分别创建了这三个儿子,并制定了儿子们的下一个元素:

/**
 * 责任链模式测试类
 */
public class ResponsiblityPatternTest {
    private static Logger getLogger(){
        Logger infoLog = new InfoLog(Logger.INFO);
        Logger debugLog = new DebugLog(Logger.DEBUG);
        Logger errorLog = new ErrorLog(Logger.ERROR);
        debugLog.setNextLogger(infoLog);
        infoLog.setNextLogger(errorLog);
        return debugLog;
    }
    public static void main(String[] args) {
        Logger logger = getLogger();
        logger.logMessage(Logger.DEBUG,"这是debug级别的log");
        System.out.println("------------------------------------");
        logger.logMessage(Logger.INFO,"这是info级别的log");
        System.out.println("------------------------------------");
        logger.logMessage(Logger.ERROR,"这是error级别的log");
    }
}

在main方法中分别调用debug,info,error级别的日志,测试结果如下:

完全符合预期,不同级别的日志请求都找到了它们对应的类去处理.

 

5.结语

忙里抽闲再度学习和复习了一波设计模式,本篇也是分享的十篇设计模式中的最后一篇,23种设计模式仅仅介绍了10篇,尚有13种未

介绍.

通过这几年做程序员的学习和体验,设计模式确实是Java程序员必备的一项技能,掌握一些常见的设计模式,可以让代码质量有质的

飞跃,其实对大部分程序员来说,能够熟练掌握6种左右设计模式,了解10种以上设计模式即可应付日常开发和基本的代码质量要求,

能完全熟练掌握23种设计模式的,那不是人,是神! 因为有很多设计模式在实际开发中不常用,时间久了也就生疏甚至忘了,所以真正

熟练掌握那么多设计模式对大部分程序员来说还是不够现实的.

掌握这些设计模式,对阅读Jdk源码和一些优秀的开源框架也比较有帮助,否则你可能很难理解代码为什么要写成那样,知其优秀而不

知其所以优秀,总之一言难尽,学海无涯啊,继续搬砖学习...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值