責任鏈模式是一種物件的行為模式。
責任鏈模式定義
責任鏈模式:避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止。
在責任鏈模式裡,很多的物件由每一個物件對其下家的引用而聯接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。比如servlet中的filter,有多層,當然,這個在Spring Security使用的更加淋漓盡致。
在責任鏈模式中發出請求的客戶端並不知道這當中的哪個物件最終處理這個請求,這樣系統的更改可以在不影響客戶端的情況下動態的重新組織和分配責任。
責任鏈模式的結構
責任鏈模式中,主要的角色有Handler和ConcreteHandler:
Handler
定義一個處理請求的介面;ConcreteHandler
具體處理類,處理它所負責的請求,可訪問它的後繼者。如果可以處理該請求,就處理,否則就將該請求轉發給它的後繼者。
責任鏈模式的實現
抽象類Handler,具體的實現都要繼承該抽象類。定義了繼任者,以及處理請求的方法。
@Data
public abstract class Handler {
protected Handler successor;//繼任者
//處理請求
public void handleRequest(int num) {}
}
複製程式碼
第一個繼任者,num小於10則處理,否則繼續傳遞。
public class ConcreteHandler1 extends Handler {
public void handleRequest(int num) {
if (num >= 0 && num < 10) {
System.out.println(this.getClass() + " 處理請求 " + num);
} else if (successor != null) {
successor.handleRequest(num);
}
}
}
複製程式碼
第二個繼任者,處理10到20的num。
public class ConcreteHandler2 extends Handler {
public void handleRequest(int num) {
if (num >= 10 && num < 20) {
System.out.println(this.getClass() + " 處理請求 " + num);
} else if (successor != null) {
successor.handleRequest(num);
}
}
}
複製程式碼
第三個繼任者,處理20到30的num。
public class ConcreteHandler3 extends Handler {
public void handleRequest(int num) {
if (num >= 20 && num < 30) {
System.out.println(this.getClass() + " 處理請求 " + num);
} else if (successor != null) {
successor.handleRequest(num);
}
}
}
複製程式碼
客戶端示例程式碼。呼叫鏈為:1->2->3。
public class TestDemo {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
//設定責任鏈的前驅和後繼
handler1.setSuccessor(handler2);
handler2.setSuccessor(handler3);
handler1.handleRequest(15);
}
}
複製程式碼
總結
本文主要介紹了行為模式的責任鏈模式。在看到一些文章處理很多if...else...
語句時,也會用責任鏈模式處理,將條件判斷分散到各個實現類中,並且這些處理類的優先處理順序可以隨意的設定,並且如果想要新增新的 handler 類也是十分簡單的,這符合開放閉合原則。不過需要注意避免責任鏈中出現迴圈引用。優缺點總結如下:
優點:
- 降低耦合度。它將請求的傳送者和接收者解耦。
- 簡化了物件。使得物件不需要知道鏈的結構。增加新的請求處理類很方便。
- 增強給物件指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。
不足之處:
- 不能保證請求一定被接收。
- 系統效能將受到一定影響,可能會造成迴圈呼叫。可能不容易觀察執行時的特徵,有礙於除錯。