簡介
責任鏈模式(Chain of Responsibility Pattern)使多個物件都有機會處理請求,從而避免了請求的傳送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。
例項
責任鏈模式包含一下角色:
Handler
: 抽象處理者。定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類或者Java介面實現。ConcreteHandler
:具體處理者。具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。Client
:客戶類
下面我們以一個簡單的請假作為示例。假設請假一天,專案經理處理就能處理,三天之類歸專案總監處理,七天內歸老闆處理,請假不允許超過七天。 抽象處理者
public abstract class AbstractHandler {
/**
* 下一個處理物件
*/
private AbstractHandler next;
/**
* 處理請假
*
* @param leaveDays 天數
* @return 處理結果
*/
public final String handleLeave(int leaveDays) {
if (this.getLeaveDays() >= leaveDays) {
return this.handle();
} else {
if (Objects.nonNull(next)) {
return next.handleLeave(leaveDays);
} else {
return "大老闆都不能處理你的假期了~~";
}
}
}
/**
* 具體處理
*
* @return 處理結果
*/
protected abstract String handle();
/**
* 每個處理類能處理的天數,資料可以使資料庫獲取,這裡簡單就寫死了
*
* @return 請假天數
*/
protected abstract Integer getLeaveDays();
/**
* 設定下一個處理類
*
* @param next
*/
public void setNext(AbstractHandler next) {
this.next = next;
}
}
複製程式碼
具體處理者
// 專案經理處理
public class PMHandler extends AbstractHandler {
@Override
protected String handle() {
return "你的請假被專案經理處理了";
}
@Override
protected Integer getLeaveDays() {
return 1;
}
}
// 專案總監處理
public class PDHandler extends AbstractHandler {
@Override
protected String handle() {
return "你的請假被專案總監處理了";
}
@Override
protected Integer getLeaveDays() {
return 3;
}
}
// 大老闆處理
public class BossHandler extends AbstractHandler {
@Override
protected String handle() {
return "你的請假被大老闆處理了";
}
@Override
protected Integer getLeaveDays() {
return 7;
}
}
複製程式碼
客戶端
@Test
public void test() {
PMHandler pmHandler = new PMHandler();
PDHandler pdHandler = new PDHandler();
BossHandler bossHandler = new BossHandler();
pmHandler.setNext(pdHandler);
pdHandler.setNext(bossHandler);
String leaveRes = pmHandler.handleLeave(1);
System.out.println(leaveRes);
String leaveRes1 = pmHandler.handleLeave(3);
System.out.println(leaveRes1);
String leaveRes2 = pmHandler.handleLeave(7);
System.out.println(leaveRes2);
String leaveRes3 = pmHandler.handleLeave(8);
System.out.println(leaveRes3);
}
複製程式碼
類圖
優點
- 降低耦合度。它將請求的傳送者和接收者解耦;
- 簡化了物件。使得物件不需要知道鏈的結構;
- 增強給物件指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任;
- 增加新的請求處理類很方便。
缺點
- 請求沒有明確的接收者,不能保證它一定會被處理,該請求可能一直到鏈的末端都得不到處理;
- 對於比較長的職責鏈,請求的處理可能涉及到多個處理物件,系統效能將受到一定影響,而且在進行程式碼除錯時不太方便,可能會造成迴圈呼叫。
適用場景
- 有多個物件可以處理同一個請求,具體哪個物件處理該請求由執行時刻自動確定;
- 在不明確指定接收者的情況下,向多個物件中的一個提交一個請求;
- 可動態指定一組物件處理請求。
總結
責任鏈模式有兩種使用形式:純責任鏈模式和不純的責任鏈模式。
如果一個類要麼承擔責任處理請求要麼將請求踢給下一個皮球,則被稱為純責任鏈模式;如果一個類承擔了一部分責任,還將請求踢給下一個皮球,則被稱為不純的責任鏈模式。純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現。