天天看点

浅学设计模式之职责链模式(14/23)

1. 职责链模式的概念

职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这个条链传递该请求,直到有一个对象处理它为止。

在Java/Android开发中,这个模式我们并不陌生,比如Java的类加载机制,“双亲委托”模型,Android中触摸事件的传递机制,都体现了职责链模式。

以上面的模型来理解责任链模式,对于一个事件来说,它并不需要知道谁来处理它,这样就解除了事件和处理事件的对象的耦合。

2. UML图

浅学设计模式之职责链模式(14/23)

来看看样板代码。

首先是​

​Handler​

​类,它是处理者类的基类,声明一个请求处理的方法,并在其中保持一个对下一个处理节点Handler对象的引用。

public abstract class Handler  {
    protected Handler successor; //下一节点的处理者
    
    /**
    * 处理请求
    */
    public abstract void handleRequest(String condition);
}      

接着是具体的处理者 ​

​ConcreteHandler​

​,对请求进行处理,如果不能处理则将该请求转发给下一个Handler对象的引用。

public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String condition) {
        if (condition.equals("ConcreteHandler1")) {
            System.out.println("ConcreteHandler1 handler");
        } else {
            successor.handleRequest(condition);
        }
    }
}      

最后是客户端类:

public static void main(String[] args){
        // 构造一个ConcreteHandlerA对象
        ConcreteHandlerA handlerA = new ConcreteHandlerA();
        
        // 构造一个ConcreteHandlerB对象
        ConcreteHandlerB handlerB = new ConcreteHandlerB();
        
        // 设置handlerA的下一个节点
        handlerA.successor = handlerB;
        
        // 设置handlerB的下一个节点
        handlerB.successor = handlerA;
        
        // 处理请求
        handlerA.handleRequest("ConcreteHandler2");
    }      

3. 责任链模式在Android中的实现

Android Framework层的触摸事件的分发机制,就是责任链模式在Android中的体现。

可以我之前总结的这篇:​​​源码分析View的事件分发​​

如果我们要在Android的代码中实现责任链模式,一个很好的应用就是“有序广播”,通过它我们可以轻松的实现全局的责任链事件的处理。

下面我们实现一个接受广播的广播接收器:

public class FirstReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 获取Intent中附加的限制值
        int limit = intent.getIntExtra("limit", -1001);

        //如果限制值等于1000, 则处理, 否则继续转发给下一个Receive
        if (limit == 1000) {
            Log.d("iterator pattern", "FirstReceiver 接收");
            //终止广播
            abortBroadcast();
        } else {
            //添加信息发送给下一个Receiver
            Bundle b = new Bundle();
            b.putString("new", "Message from FirstReceiver");
            setResultExtras(b);
        }
    }
}      

之后的广播接收器和这个差不多,他们只要处理自己能处理的限制值,就会通过 ​

​abortBroadcast()​

​来终止广播。

4. 小结

责任链的使用场景:多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。

  • 处理者和请求者在关系上解耦。
  • 我们可以随时地增加或则修改处理一个请求的结构,这提高了代码的灵活性。
  • 责任链模式最大的缺点就是对链中请求处理者的遍历,如果处理者太多,那么遍历必定会影响性能,特别是在一些递归调用中,要慎重使用。