設計模式--責任鏈模式ChainOfResponsibility(行為型)
1 定義:
1.1 定義: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.(使多個物件都有機會處理請求,從而避免了請求的傳送者和接受者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。)
1.2 通用類圖:
責任鏈模式的重點是在“鏈”上,由一條鏈去處理相似的請求在鏈中決定誰來處理這個請求,並返回相應的結果。
1.3 通用程式碼:
/**
* @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you
* all.
*/
public abstract class Handler {
private Handler nextHandler;
// 每個處理者都必須對請求做出處理
public final Response handlerMessage(Request request) {
Response response = null;
// 判斷是否是自己的處理級別
if (this.getHandlerLevel().equals(request.getRequestLevel())) {
response = this.echo(request);
} else { // 不屬於自己的處理級別
// 判斷是否有下一個處理者
if (this.nextHandler != null) {
response = this.nextHandler.handlerMessage(request);
} else {
// 沒有適當的處理者,業務自行處理
}
}
return response;
}
// 設定下一個處理者是誰
public void setNext(Handler _handler) {
this.nextHandler = _handler;
}
// 每個處理者都有一個處理級別
protected abstract Level getHandlerLevel();
// 每個處理者都必須實現處理任務
protected abstract Response echo(Request request);
}
// 抽象的處理者實現三個職責:一是定義一個請求的處理方法handleMessage,唯一對外開放的方法;二是定義一個鏈的編排方法setNext,設定下一個處理者;三是定 義了具體的請求者必須實現的兩個方法:定義自己能夠處理的級別與具體的處理任務。
public class ConcreteHandler1 extends Handler {
// 定義自己的處理邏輯
protected Response echo(Request request) {
// 完成處理邏輯
return null;
}
// 設定自己的處理級別
protected Level getHandlerLevel() {
// 設定自己的處理級別
return null;
}
}
public class ConcreteHandler2 extends Handler {
// 定義自己的處理邏輯
protected Response echo(Request request) {
// 完成處理邏輯
return null;
}
// 設定自己的處理級別
protected Level getHandlerLevel() {
// 設定自己的處理級別
return null;
}
}
public class ConcreteHandler3 extends Handler {
// 定義自己的處理邏輯
protected Response echo(Request request) {
// 完成處理邏輯
return null;
}
// 設定自己的處理級別
protected Level getHandlerLevel() {
// 設定自己的處理級別
return null;
}
}
public class Level {
// 定義一個請求和處理等級
}
public class Request {
// 請求的等級
public Level getRequestLevel() {
return null;
}
}
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類,直接返回鏈中第一個處理者,具體鏈的設定不需要高層次模組關係,這樣更簡化了高層次模組的呼叫,減少模組間的耦合,提高系統的靈活性。
2 優點
2.1 最顯著就是:請求和處理分開。請求者可以不用知道是誰處理的,處理者可以不用知道請求的全貌,兩者解耦,提高系統的靈活性。
2.2 承接第一點,個人認為最大的好處就是把星狀的耦合關係變成直線型的耦合關係,使原本“一對多”的耦合關係,變為“一對一”耦合(因為事件只與第一個處理物件耦合,每個處理物件又只與後面一個物件耦合)。
3 缺點
3.1 效能問題:每個請求都從鏈頭遍歷到鏈尾,特別是在鏈比較長的時候,效能是一個非常大的問題。
3.2 不便於除錯,由於採用了類似於遞迴的方式,除錯時邏輯比較複雜。
4 應用場景
責任鏈模式的核心是遮蔽了請求的處理過程(即請求者可以不用知道到底是誰來處理的)。
其表面上看來,用物件導向的“連結串列+遍歷+函式呼叫+判斷”來替換程式導向的“若干if-else判斷”,以至於我起初認為這個模式完全是為了物件導向取代if判斷而生的。
但實質上,降低了請求與處理物件之間的耦合,分析見上。
4.1某一請求根據條件,只需少數(或一個)物件處理,但卻需要在較多物件中做選擇的情況;
4.2 請求處理時,不能越權,只能按步驟判斷處理的情況;
5 注意事項
5.1 鏈長需要控制,應避免出現超長鏈的情況;
6 擴充套件
6.1某事件需要多個大物件共同參與處理的情況(每個物件處理一部分,但非每個物件每時每刻都參與的情境);[冒似此景下最能發揮效能,但要考慮設計是否有問題。。。]
7 範例
(小例,請假,因為不能越權嘛,你只能訪問直接上司。。。)
類圖如下:
原始碼
package _10_ChainOfResponsibility;
public abstract class Handler {
private Handler nextHandler;
public final AskForLeave handleMessage(AskForLeave ask) {
AskForLeave leave = null;
if (ask.getDays() <= this.getDays()) {
leave = this.echo(ask);
} else {
if (this.nextHandler != null)
leave = this.nextHandler.handleMessage(ask);
else
;// 沒有處理者
}
return leave;
}
// 設定下一者
public void setNext(Handler handler) {
nextHandler = handler;
}
// 每個處理者都有處理等級
protected abstract int getDays();
// 每個處理者都必須實現處理任務
protected abstract AskForLeave echo(AskForLeave ask);
}
public class HeadHandler extends Handler {
@Override
protected int getDays() {
return 1;
}
@Override
protected AskForLeave echo(AskForLeave ask) {
ask.setResult(true);
return ask;
}
}
public class ManagerHandler extends Handler {
@Override
protected int getDays() {
return 3;
}
@Override
protected AskForLeave echo(AskForLeave ask) {
ask.setResult(true);
return ask;
}
}
public class ChiefHandler extends Handler {
@Override
protected int getDays() {
return 7;
}
@Override
protected AskForLeave echo(AskForLeave ask) {
ask.setResult(true);
return ask;
}
}
public class HumanResourceHandler extends Handler {
@Override
protected int getDays() {
return 15;
}
@Override
protected AskForLeave echo(AskForLeave ask) {
ask.setResult(true);
return ask;
}
}
public class AskForLeave {
private int days;
private boolean result = false;
public AskForLeave(int days) {
this.days = days;
}
public boolean getResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
public int getDays() {
return days;
}
}
public class Client {
public static void main(String[] args) {
Handler h1 = new HeadHandler();
Handler h2 = new ManagerHandler();
Handler h3 = new ChiefHandler();
Handler h4 = new HumanResourceHandler();
h1.setNext(h2);
h2.setNext(h3);
h3.setNext(h4);
AskForLeave ask1 = new AskForLeave(5);
AskForLeave ask2 = new AskForLeave(15);
AskForLeave ask3 = new AskForLeave(16);
h1.handleMessage(ask1);
System.out.println("請假5天,是否批准? " + ask1.getResult());
h1.handleMessage(ask2);
System.out.println("請假15天,是否批准? " + ask2.getResult());
h1.handleMessage(ask3);
System.out.println("請假16天,是否批准? " + ask3.getResult());
}
}
請假5天,是否批准? true
請假15天,是否批准? true
請假16天,是否批准? false
相關文章
- Java責任鏈模式(ChainofResponsibility模式)Java模式AI
- 行為型設計模式 - 責任鏈模式詳解設計模式
- 設計模式 —— 責任鏈模式設計模式
- 設計模式-責任鏈模式設計模式
- 設計模式(責任鏈模式)設計模式
- 設計模式——責任鏈模式設計模式
- 設計模式之責任鏈模式設計模式
- 設計模式(三) 責任鏈模式設計模式
- 設計模式(十四) 責任鏈模式設計模式
- 設計模式(十八):責任鏈模式設計模式
- PHP 設計模式之責任鏈模式PHP設計模式
- 設計模式系列之「責任鏈模式」設計模式
- JAVA設計模式之責任鏈模式Java設計模式
- 極簡設計模式-責任鏈模式設計模式
- 設計模式(四)OkHttp的責任鏈模式設計模式HTTP
- 設計模式第七講-責任鏈模式設計模式
- 我的Java設計模式-責任鏈模式Java設計模式
- 23種設計模式(六)-責任鏈設計模式設計模式
- 設計模式 | 責任鏈模式及典型應用設計模式
- Rust語言之GoF設計模式:責任鏈模式RustGo設計模式
- 設計模式(9)-責任鏈模式詳解(易懂)設計模式
- 責任鏈模式模式
- 設計模式:如何優雅地使用責任鏈模式設計模式
- Go 實現常用設計模式(十)責任鏈模式Go設計模式
- 設計模式之責任鏈模式——Java語言描述設計模式Java
- 每天一個設計模式之責任鏈模式設計模式
- C#設計模式-責任鏈模式(Chain of Responsibility Pattern)C#設計模式AI
- 設計模式-職責鏈模式設計模式
- 責任鏈模式妙用模式
- 責任鏈模式探究模式
- 「責任鏈模式」栗子模式
- Java設計模式(5)之責任鏈模式學習總結Java設計模式
- Java進階篇設計模式之八 ----- 責任鏈模式和命令模式Java設計模式
- 不得不知的責任鏈設計模式設計模式
- 設計模式之-職責鏈模式設計模式
- 設計模式之【職責鏈模式】設計模式
- 「補課」進行時:設計模式(9)——在請假中使用的責任鏈模式設計模式
- PHP-責任鏈模式PHP模式