天天看點

淺學設計模式之職責鍊模式(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. 小結

責任鍊的使用場景:多個對象可以處理同一請求,但具體由哪個對象處理則在運作時動态決定。

  • 處理者和請求者在關系上解耦。
  • 我們可以随時地增加或則修改處理一個請求的結構,這提高了代碼的靈活性。
  • 責任鍊模式最大的缺點就是對鍊中請求處理者的周遊,如果處理者太多,那麼周遊必定會影響性能,特别是在一些遞歸調用中,要慎重使用。