责任链模式:步步为营。



文章目录

  • 责任链模式:步步为营。
  • 前言
  • 一、责任链模式的作用
  • 二、如何实现责任链
  • 1 既然是责任链,那么就需要一个链路的承载体 ChainBody
  • 2 责任链中每一步都是一个抽象类,因为承载体仅仅是构造链路顺序,里面不放置任何具体业务逻辑:步骤抽象类
  • 3 具体步骤执行,继承步骤抽象类
  • 4 开始测试
  • 总结



前言

责任链模式个人认为算是设计模式中比较复杂的一个;顾名思义 责任链,这个模式的思想是: 构造一个个的,有规则的步骤,拼接为一个链路,然后执行,例如: 制作鸡蛋炒饭
第一步: 做米饭
第二步: 煎蛋
第三步: 一起炒

每一步有每一步骤的职责,当有需求改动的时候,可以灵活调整,例如我想放入葱花,那么只需要再加一步即可;


一、责任链模式的作用

旨在解决复杂业务逻辑的代码堆积化,使代码接口清晰;

1 将一个臃肿的业务逻辑,有序的拆分为多个子步骤,可以让逻辑更清晰,逻辑层代码简洁
2 多个步骤之间通常顺序不可变,但如果业务逻辑无先后顺序,也可以调整顺序,这样就会使得使用的时候,非常灵活,对于之后的业务变更等需求,扩展性非常好,扩展很简单;否则就要改动一个业务逻辑臃肿的代码,改动之前还要理清业务逻辑,而责任链方式,则只需要添加一步,甚至不用看其他代码,只要遵循已有原则,实现自己的业务逻辑就行了;
3 责任链构建好之后,当遇到同种业务逻辑,而执行顺序不同的时候,可以直接通过改变构架责任链的顺序,而快速实现编码;

二、如何实现责任链

例如: 我现在有一个数字,要加工,第一步加法 第二步减法 第三步乘法 ;每一步都有各自的处理逻辑,而且通常不会改变的部分,将他单独提取为一步,之后可能变动的,仅仅是顺序;
开始编码:

1 既然是责任链,那么就需要一个链路的承载体 ChainBody
@Data
public class ChainBody {

    private ChainStep head;

    private ChainStep tail;


    public void addChainStep(ChainStep chainStep) {

        if (null == head) {
            head = chainStep;
            tail = chainStep;
            return;
        }
        tail.setNextStep(chainStep);
        tail = chainStep;
    }

    public Integer start(Integer num) {
        if (null != head) {
            return head.handel(num);
        }
        return num;
    }
}

1 addChainStep 这个方法就是在构造一个链路,其中 tail.setNextStep(chainStep); 就在将新增加的一个步骤,作为tail这个节点的tail
2 addChainStep 这个方法中,tail一直作为head的构造子链路的一个中间变量,然后每次tail 都是最新的一个节点,为了继续构造子链路做准备
3 start 方法是为了 开始执行责任链而存在,这里面的具体执行也是交给具体步骤类执行,这里仅仅作为一个执行入口

2 责任链中每一步都是一个抽象类,因为承载体仅仅是构造链路顺序,里面不放置任何具体业务逻辑:步骤抽象类
public abstract class ChainStep {

    private ChainStep chainStep;

    public void setNextStep(ChainStep chainStep) {
        this.chainStep = chainStep;
    }

    public Integer handel(Integer num) {
        Integer res = this.doHandel(num);
        if (null != this.chainStep) {
             res = this.chainStep.handel(res);
        }
        return res;
    }

    abstract int doHandel(Integer num);
}

1 这就是步骤抽象类,setNextStep 上文已经说到
2 handel 就是入口的延续,这里作为调度具体执行步骤的一个逻辑,当有子链路的时候(tail 不为空),那么当前节点还未结束,继续执行,直到无tail后,那么执行结束,这里相当于一个递归执行
3 doHandel 是一个抽象方法,上个方法是具体步骤调度逻辑,而这个方法就是要真正的步骤类执行了,他是一个抽象方法,也就是要交给具体的步骤类去执行具体方法;

3 具体步骤执行,继承步骤抽象类
public class Step1 extends ChainStep {

    @Override
    int doHandel(Integer num) {
        return num + 5;
    }
}
public class Step2 extends ChainStep {

    @Override
    int doHandel(Integer num) {
        return num * 5;
    }
}

public class Step3 extends ChainStep {

    @Override
    int doHandel(Integer num) {
        return num - 2;
    }
}
4 开始测试
public class Test {

    public static void main(String[] args) {
        ChainBody chainBody = new ChainBody();
        chainBody.addChainStep(new Step1());
        chainBody.addChainStep(new Step2());
        chainBody.addChainStep(new Step3());
        
        //chainBody.addChainStep(new Step1());
        //chainBody.addChainStep(new Step2());
        System.out.println(chainBody.start(10));
    }
}

1 如果每个步骤里面的业务逻辑非常复杂,那么是不是这样的代码很简洁?
2 如果业务逻辑不相关,可以灵活调整执行顺序,灵活添加执行步骤

断点执行,查看责任链的链路

一句话设计模式5:责任链模式_java


可以看到,这条完整的链路,然后根据这个链路,去递归执行;执行结果

一句话设计模式5:责任链模式_设计模式_02


总结

责任链的难点,在于构造责任链的链路,然后做好业务抽象,将每个业务相对独立的部分单独拆分出来,为了以后的业务变更做好预留,这样设计的代码,业务扩展性会非常好,当有新的链路增加进来,改动也会非常快,代码思路,逻辑更清晰;