看!责任链模式来了

228 阅读6分钟

责任链模式.png

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

今天我们一起来学习,使用频率很高,且实战性比较强的一种模式----组合模式。多唠叨几句,我本月将会对java的设计模式精讲,欢迎点击头像,关注我的专栏,我会持续更新,加油!

设计模式之单例模式

设计模式之工厂模式

设计模式之建造者模式

设计模式之代理模式

设计模式之访问者模式

设计模式之适配器模式

设计模式之命令者模式

java状态模式 | 随时随地监控状态改变

java观察者模式 | 如何通知事物的变化

java备忘录模式 | 如何记录历史信息

java迭代器模式模式 | 如何对各个元素进行访问

java享元模式 | 如何共享对象

java解释器模式 | 自定义规则实现逻辑

java桥接模式 | 抽象与不同实现的绑定

java门面模式 | 如何提高接口的高可用

持续更新中......

话不多说,进入正题

责任链模式

责任链模式,重要的体现在这个链上面,从上到下,就是一条链式调用,A调B,B调C。

官方定义:通过为多个对象提供处理请求的机会,避免将请求的发送者与其接收者耦合。链接接收对象并沿着链传递请求,直到对象处理它。

注意:定义中说了一个关键点:通过构建一个处理流水线来对一次请求进行多次的处理。

前几天我在京东上遇到一个场景,去年买的耳机坏掉了,今天正好在有效期内,那么经过协商在京东申请售后。我仔细观察了他的状态。我先申请售后,然后客服给我打过来电话(不得不说京东服务真的是好),会先打开订单系统查询你提供的订单信息并确认是否正确,确认后再使用物流系统通知快递小哥上门取件,快递小哥取件后会返回商品让仓储系统进行确认,并通知商品系统……这样的一个过程就是责任链模式的真实应用。

在我们日常的开发中,一个经典的使用场景就是参数的判断,比如我们要判断A参数是否符合条件,B参数是否符合条件,接着C判断,如果都符合,接着往下走,去执行相关逻辑。

下面我们看下图

image.png

从该图中,我们能看出责任链模式其实只有两个关键角色。

  • 处理类(Handler):可以是一个接口,用于接收请求并将请求分派到处理程序链条中(实际上就是一个数组链表),其中,会先将链中的第一个处理程序放入开头来处理。

  • 具体处理类(HandlerA、B、C):按照链条顺序对请求进行具体处理。

接下来我们用实际场景来演示下代码

代码展示

我用我们公司在钉钉提交请假申请的场景来演示下代码

image.png

我们可以看到抄送人经过同意之后,会提交给直接主管,接着会给人力专员

//请假实体
@Builder
public class LeaveRequest {
    //天数
    private int leaveDays;

    //姓名
    private String name;
    
    //请假事由
    private String reason;
}


//请假责任链抽象处理类
public class AbstractLeaveHandler {
    
    //领导名称
    protected String handlerName;

    //下一个处理节点(即更高级别的领导)
    protected AbstractLeaveHandler nextHandler;

    //设置下一节点
    protected void setNextHandler(AbstractLeaveHandler handler){
        this.nextHandler = handler;
    }

    //处理请假的请求,子类实现
    protected void handlerRequest(LeaveRequest request){

    }
}

抄送人(一般是人事部)

//抄送人接收
public class CCLeaveHandler extends AbstractLeaveHandler{
    public CCLeaveHandler(String name) {
        this.handlerName = name;
    }

    @Override
    protected void handlerRequest(LeaveRequest request) {
        //超过10天 不准假
        if(request.getLeaveDays() > 10){
            System.out.println("抄送人:" + handlerName + ",已经处理;流程结束。");
            return;
        }
        if(null != this.nextHandler){
              //审批,传送给下一个责任链
            this.nextHandler.handlerRequest(request);
        }else{
            System.out.println("拒绝!");
        }

    }
}

直接主管类(部门直接领导)

//直接主管
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler{
    public DirectLeaderLeaveHandler(String name) {
        this.handlerName = name;
    }

    @Override
    protected void handlerRequest(LeaveRequest request) {
        System.out.println("直接领导:" + handlerName + ",开始处理请假。");
    
        if(null != this.nextHandler){
              //审批,传送给下一个责任链
            this.nextHandler.handlerRequest(request);
        }else{
            System.out.println("拒绝!");
        }
    }
}

人力专员


//hr
public class HRLeaveHandler extends AbstractLeaveHandler{
    public HRLeaveHandler(String name) {
        this.handlerName = name;
    }

    @Override
    protected void handlerRequest(LeaveRequest request) {
        System.out.println("人力专员:" + handlerName + ",已经处理;流程结束。");
        
        if(null != this.nextHandler){
              //审批
            this.nextHandler.handlerRequest(request);
        }else{
            System.out.println("执行结束!");
        }
    }
}

public class DingDingTest {
    public static void main(String[] args) {
        LeaveRequest request = LeaveRequest.builder().leaveDays(20).name("小明").build();


        CCLeaveHandler cc = new CCLeaveHandler("抄送人小李");
        DirectLeaderLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler("直接领导,王总");
        HRLeaveHandler hrLeaveHandler = new HRLeaveHandler("人力专员,小郭");

        cc.setNextHandler(deptManagerLeaveHandler);
        directLeaderLeaveHandler.setNextHandler(gManagerLeaveHandler);
        hrLeaveHandler.handlerRequest(request);
    }
}

从这段代码实现可以看出,责任链模式的实现非常简单,每一个具体的处理类都会保存在它之后的下一个处理类。当处理完成后,就会调用设置好的下一个处理类,直到最后一个处理类不再设置下一个处理类,这时处理链条全部完成。

责任链模式就像工厂的流水线作业一样,按照某一个标准化的流程来执行,用于规则过滤、Web 请求协议解析等具备链条式的场景中,通过拆分不同的处理节点来完成整个流程的处理。

责任链模式在实际代码中也是应用比较广泛的。且容易理解的。

OK 今天的代码部分就到这里,我们总结下

总结

为什么使用责任链模式?

  • 第一个,解耦使用者和后台庞大的流程化处理

  • 第二个,为了动态更换流程处理中的处理对象。比如,在请假流程中,申请人一般会提交申请给直接领导审批,但有时直接领导可能无法进行审批操作,这时系统就可以更换审批人到其他审批人,这样就不会阻塞请假流程的审批。

优点嘛,我个人认为 1、增强了具体处理类的职责独立性

2、这避免了使用众多的 if 或者 if···else 语句。简化了对象之间前后关联处理的复杂性。每个对象只需存储一个指向后继者的引用,不需保持其他所有处理者的引用,

image.png

缺点还是有的,这样的话,类可能会增多。第二,调试难度增大,出现问题,调试起来不好调试。第三,也会在一定程度上影响性能。

netty当中的责任链

这里稍微提下,牛逼框架Netty当中也有用到责任链。大家下去可以了解下,这里后面将netty会讲下

Netty中的ChannelPipeline责任链: pipeline管道保存了通道所有处理器信息,创建channel时自动创建一个专有的pipeline,入站事件和出站事件会调用pipeline上的处理器

线外知音

感谢你的阅读,如果你感觉学到了东西,麻烦您点赞,关注。

我已经将本章收录在专题里,点击下方专题,关注专栏,我会每天发表干货,本月我会持续输入设计模式。

加油! 我们下期再见!