责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

一、先来简单的实现,理一下思路:

  • 每个接收者应该知道是否处理这个任务
  • 每个接收者应该持有下一个接收者,当自己不处理时,把任务向下传递

向上抽取出BaseReceiver

public abstract class BaseReceiver {

    /**
     * 是否处理任务
     */
    private boolean isExecute;

    /**
     * 下一个任务接收者
     */
    private BaseReceiver nextReceiver;

    public BaseReceiver(boolean isExecute) {
        this.isExecute = isExecute;
    }

    /**
     * 绑定下一个任务接收者
     * @param receiver
     */
    public void addNextReceiver(BaseReceiver receiver) {
        nextReceiver = receiver;
    }

    /**
     * 处理任务
     */
    public abstract void execute();

    /**
     * 任务流,每个任务判断自己是否执行,不执行就传递给下一个任务
     */
    public void run() {
        if (isExecute) {
            execute();
        }else if (nextReceiver != null) {
            nextReceiver.run();
        }
    }

}

创建出三个接收者:Receiver1Receiver3Receiver3

public class Receiver1 extends BaseReceiver {

    public Receiver1(boolean isExecute) {
        super(isExecute);
    }

    @Override
    public void execute() {
        System.out.println("Receiver1执行了");
    }
}

测试调用:

    public static void main(String[] args) {

        Receiver1 receiver1 = new Receiver1(false);
        Receiver2 receiver2 = new Receiver2(true);
        Receiver3 receiver3 = new Receiver3(false);

        receiver1.addNextReceiver(receiver2);
        receiver2.addNextReceiver(receiver3);

        receiver1.run();
    }

输出结果:

Receiver2执行了

揍是这么简单。

二、再来一种实现,其实还是一样的,只是封装了一下,上面那种addNextReceiver()感觉有点不爽,这次用一个manager管理一下。
先看完代码再解释,首先还是抽取的一个接收者接口:

public interface IBaseReceiver {

    /**
     *
     * @param condition 判断任务是否执行的条件
     * @param receiverManager 接受者管理器,也实现了IBaseReceiver
     */
    public void execute(String condition, IBaseReceiver receiverManager);

}

condition就是第一种实现里的是否执行的条件,这里用一个String表示。
然后是Receiver1Receiver3Receiver3

public class Receiver1 implements IBaseReceiver {
    @Override
    public void execute(String condition, IBaseReceiver receiverManager) {
        if (condition == "1") {
            System.out.println("Receiver1执行了任务");
        }else {
            receiverManager.execute(condition, receiverManager);
        }
    }
}

这里是否处理的条件,就是判断String的值,具体业务中这里的判断条件灵活修改。
看到上面一直在传递一个也实现了IBaseReceiverreceiverManager,肯定是不理解为什么,这里看一下这个manager的实现:

public class ReceiverManager implements IBaseReceiver {

    /**
     * 接收者集合
     */
    private List<IBaseReceiver> receivers = new ArrayList<>();

    /**
     * 添加接收者
     * @param receiver
     */
    public void addReceiver(IBaseReceiver receiver) {
        receivers.add(receiver);
    }

    /**
     * 当前接收者角标
     */
    private int index = 0;

    /**
     * 每次调用一次就会进行index++操作,用这种方式实现了接收者的向下传递
     * @param condition 判断任务是否执行的条件
     * @param receiverManager 接受者管理器,也实现了IBaseReceiver
     */
    @Override
    public void execute(String condition, IBaseReceiver receiverManager) {

        if (receivers.isEmpty()) return;

        if (index >= receivers.size()) return;

        IBaseReceiver receiver = receivers.get(index);

        index++;

        receiver.execute(condition, receiverManager);
    }
}

看完调用再解释上面的函数,调用:

        ReceiverManager receiverManager = new ReceiverManager();
        receiverManager.addReceiver(new Receiver1());
        receiverManager.addReceiver(new Receiver2());
        receiverManager.addReceiver(new Receiver3());
        receiverManager.execute("2", receiverManager);

运行结果:

Receiver2执行了任务

理一下上面的流程,这里的调用有点绕,但是很巧妙:
调用的时候receiverManager执行execute()时,参数直接传入了他自己,那直接进入到ReceiverManagerexecute ()方法:

    public void execute(String condition, IBaseReceiver receiverManager) {

        ...
        //此时index为0,receiver为Receiver1的实例对象
        IBaseReceiver receiver = receivers.get(index);
        index++;
        receiver.execute(condition, receiverManager);
    }

index的初始值是0,那直接拿到集合中的第一个元素,也就是Receiver1的一个实例,执行Receiver1execute(),并且还是把这个receiverManager传递了过去,注意在这之前进行了index++,也就是传递过去的这个receiverManager中的index已经等于1了。
然后来到Receiver1中:

public class Receiver1 implements IBaseReceiver {
    @Override
    public void execute(String condition, IBaseReceiver receiverManager) {
        if (condition == "1") {
            System.out.println("Receiver1执行了任务");
        }else {
            receiverManager.execute(condition, receiverManager);
        }
    }
}

因为传递过来的condition为2,不满足执行条件,所以走了else的流程,用传递过来的receiverManager继续执行execute(),还是要注意,这个receiverManager中的index已经是等于1的,那么就又回到了ReceiverManager的代码中:

    public void execute(String condition, IBaseReceiver receiverManager) {

        ...
        //此时index为1,receiver为Receiver2的实例对象
        IBaseReceiver receiver = receivers.get(index);
        index++;
        receiver.execute(condition, receiverManager);
    }

因为receiverManager一直是同一个对象,只是传递来传递去,没有new,所以这里的index为1,拿到的receiver为Receiver2的实例对象,那么就进入了Receiver2execute(),这里逻辑就不再贴了,跟进入Receiver1的是一样的,只是判断条件不同,因为条件满足,Receiver2直接处理了任务,不再继续进行,如果条件还是不满足,继续Receiver3,这么一直循环下去。
还是乱的话,跟着代码理一下,其实很简单很清晰,也有点妙。
这种设计模式的使用也很常见,Android源码中的事件传递,Okhttp中的拦截器,好多好多,都是使用到。

项目地址

推荐阅读更多精彩内容