责任链模式

822 阅读2分钟
责任链模式的定义

使多个对象都有机会处理请求, 从而避免了请求的发送者和接收者之间的耦合关系, 将这些对象连成一条链, 并沿着这条链传递该请求, 直到有对象处理它为止.

责任链模式的使用场景

多个对象可以处理同一请求, 单具体由哪个对象处理则在运行时动态决定. 在请求处理者不明确的情况下向多个对象中的一个提交一个请求, 需要动态指定一组对象处理请求.

假设一种场景

上游发送一条消息, 下游接收这条消息并跟根据消息类型进行处理.

public class Msg {
    int messageType;
}
public void send() {
    postMsg(msg);
}
不使用责任链模式的写法
public void handleMsg(Msg msg) {
    switch(msg.messageType) {
        case 1:handle1(msg);breack;
        case 2:handle2(msg);breack;
        case 3:handle3(msg);breack;
        ...
    }
}

上面这种写法, 随着type类型的增加, switch...case的代码量也势必增加, 维护起来也比较麻烦. 如果参考像retrofit中使用的责任链模式对请求进行处理, 责任链上各个节点各尽其责. 只用关心属于自己的type的情况

使用责任链模式
public interface INode {
    boolean handleMsg(Msg msg);
}
public class Node1 implements INode {
    // true: 自己可以处理, false: 自己不能处理;
    public boolean handleMsg(Msg msg) {
        if (...) {
            return true;
        }
        // 不能处理, 将Msg抛给下一个Node去处理
        return false;
    }
}
public List<Node> nodes = new ArrayList();
public void init() {
    nodes.add(new Node1());
    nodes.add(new Node2());
    nodes.add(new Node3());
}
// 当收到消息时, 遍历集合, 对Msg进行处理
public void handleMsg(Msg msg) {
    for(int i = 0; i < nodes.size(); i++) {
        if (nodes.get(i).handleMsg(msg)) {
            break;
        }
    }
}

如果有新增的messageType的情况时, 不需要维护大量的switch...case的代码, 只需要新增一个Node, 然后将该Node添加到集合中即可, 如果觉得将Node添加到集合中也比较麻烦, 可以考虑使用注解处理器, 在编译时, 将被注解的Node自动添加到集合中, 省去了每次新增Node, 将Node添加到集合的操作.