定義
責任鏈的定義如下:
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方法中判斷是否已經超過其閾值,超過則不允許該鏈建立,避免無意識地破壞系統性能。