再說設計模式-責任鏈模式

定義

責任鏈的定義如下:

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有對象處理它爲止。

責任鏈模式的重點是在“鏈”上,由一條鏈去處理相似的請求在鏈中決定誰來處理這個請求,並返回相應的結果,其通用類圖如下:


責任鏈模式的核心在“鏈”上,“鏈”是由多個處理者ConcreteHandler組成的,我們先看一下抽象Handler類,代碼如下:

public abstract class Handler {
  private Handler nextHandler;
  // 每個處理者都必須對請求做出處理
  public final Response HandleMessage(Request request) {
    Response response = null;
    // 判斷是否是自己的處理級別
    if (this.getHandlerLevel().equals(request.getRequestLevel())) {
      response = this.echo(request);
    } else {
      // 判斷是否有下一個處理者
      if (this.nextHandler != null) {  
          response = this.nextHandler.handleMessage(request);
      } else {
         // 沒有適當的處理者,業務自行處理
      }
    }
    return response;
  }
  // 設置下一個處理者是誰
   public void setNext(Handler _handler) {
      this.nextHandler = _handler;
   }
  // 每一個處理者都有一個處理級別
  protected abstract Level getHandlerLevel();
  // 每個處理者都必須實現處理任務
  protected abstract Response echo(Request request);
}

抽象的處理者實現三個職責:

  • 定義一個請求的處理方法handleMessage,唯一對外開放的方法;
  • 定義了一個鏈的編排方法setNext,設置下一個處理者;
  • 定義了具體的請求者必須實現的兩個方法:自己能夠處理的級別getHandlerLevel和具體的處理任務echo;

ps 在責任鏈模式中一個請求發送到鏈中後,前一節點消費部分消息,然後交由後續節點斷續處理,最終可以有處理結果也可以沒有處理結果。

具體的處理者代碼如下:

public class ConcreteHandler1 extends Handler {
  // 定義自己的處理邏輯
  protected Response echo(Request request) {
    // ....
  }
  // 設置自己的處理級別
  protected Level getHandlerLevel() {
    // ....
  }
}

在處理者中涉及三個類:Level類負責定義請求和處理級別,Request類負責封裝請求,Response負責封裝鏈中返回的結果,該三個類都需要根據業務產生,我們可以在實際應用中完成相關的業務填充,其框架代碼如下:
Level類:

public class Level {
  // 定義一個請求和處理等級
}

Request類:

public class Request {
  // 請求等級
  public Level getRequestLevel() {
    return null;
  }
}

Response類:

public class Response {
  // 處理者返回的數據
}

在場景類或高層模塊中對鏈進行組裝,並傳遞請求,返回結果~

場景類如下:

public class Client {
  public static void main(String[] args) {
    // 聲明所有的處理節點
    Handler handler1 = new ConcreteHandler1();
    Handler handler2 = new ConcreteHandler2();
    Handler handler3 = new ConcreteHandler3();

    // 設置鏈中的階段順序 1-->2-->3
    handler1.setNext(handler2);
    handler2.setNext(handler3);
    // 提交請求,返回結果
    Response response = handler1.handlerMessage(new Request());
  }
}

在實際應用中,一般會有一個封裝類對責任模式進行封裝,也就是替代Client類,直接返回鏈中第一個處理者,具體鏈的設置不需要高層次模塊關係,這樣,更簡化了高層次模塊的調用,減少模塊音的耦合,提高系統的靈活性。

優點

責任鏈模式將請求和處理分開。請求者可以不用知道是誰在處理的,處理者可以不用知道請求的全貌,兩者解耦,提高系統的靈活性。

缺點

責任連有兩個非常顯著的缺點:

  • 一、性能問題,每個請求都是從鏈頭遍歷到鏈尾,特別是在鏈比較長的時候,性能是一個非常大的問題。
  • 二、調試很不方便,特別是鏈條比較長,環節比較多的時候,由於採用了類似遞歸的方式,調試的時候邏輯可能比較複雜。

注意事項

鏈中節點的數量需要控制,避免出現超長鏈的情況,一般做是在Handler中設置一個最大節點數量,在setNext方法中判斷是否已經超過其閾值,超過則不允許該鏈建立,避免無意識地破壞系統性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章