作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用
javascript
和python
兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 :)
0. 專案地址
1. 什麼是“責任鏈模式”?
責任鏈模式:多個物件均有機會處理請求,從而解除傳送者和接受者之間的耦合關係。這些物件連線成為鏈式結構,每個節點轉發請求,直到有物件處理請求為止。
其核心就是:請求者不必知道是誰哪個節點物件處理的請求。如果當前不符合終止條件,那麼把請求轉發給下一個節點處理。
而當需求具有“傳遞”的性質時(程式碼中其中一種體現就是:多個if、else if、else if、else
巢狀),就可以考慮將每個分支拆分成一個節點物件,拼接成為責任鏈。
2. 優點與代價
- 優點
- 可以根據需求變動,任意向責任鏈中新增 / 刪除節點物件
- 沒有固定的“開始節點”,可以從任意節點開始
- 代價:責任鏈最大的代價就是每個節點帶來的多餘消耗。當責任鏈過長,很多節點只有傳遞的作用,而不是真正地處理邏輯。
3. 程式碼實現
為了方便演示,模擬常見的“日誌列印”場景。模擬了 3 種級別的日誌輸出:
LogHandler
: 普通日誌WarnHandler
:警告日誌ErrorHandler
:錯誤日誌
首先我們會構造“責任鏈”:LogHandler
-> WarnHandler
-> ErrorHandler
。LogHandler
作為鏈的開始節點。
如果是普通日誌,那麼就由 LogHandler
處理,停止傳播;如果是 Warn 級別的日誌,那麼 LogHandler
就會自動向下傳遞,WarnHandler
接收到並且處理,停止傳播;Error 級別日誌同理。
3.1 ES6 實現
class Handler {
constructor() {
this.next = null;
}
setNext(handler) {
this.next = handler;
}
}
class LogHandler extends Handler {
constructor(...props) {
super(...props);
this.name = "log";
}
handle(level, msg) {
if (level === this.name) {
console.log(`LOG: ${msg}`);
return;
}
this.next && this.next.handle(...arguments);
}
}
class WarnHandler extends Handler {
constructor(...props) {
super(...props);
this.name = "warn";
}
handle(level, msg) {
if (level === this.name) {
console.log(`WARN: ${msg}`);
return;
}
this.next && this.next.handle(...arguments);
}
}
class ErrorHandler extends Handler {
constructor(...props) {
super(...props);
this.name = "error";
}
handle(level, msg) {
if (level === this.name) {
console.log(`ERROR: ${msg}`);
return;
}
this.next && this.next.handle(...arguments);
}
}
/******************以下是測試程式碼******************/
let logHandler = new LogHandler();
let warnHandler = new WarnHandler();
let errorHandler = new ErrorHandler();
// 設定下一個處理的節點
logHandler.setNext(warnHandler);
warnHandler.setNext(errorHandler);
logHandler.handle("error", "Some error occur");
複製程式碼
3.2 Python3 實現
class Handler():
def __init__(self):
self.next = None
def set_next(self, handler):
self.next = handler
class LogHandler(Handler):
def __init__(self):
super().__init__()
self.__name = "log"
def handle(self, level, msg):
if level == self.__name:
print('LOG: ', msg)
return
if self.next != None:
self.next.handle(level, msg)
class WarnHandler(Handler):
def __init__(self):
super().__init__()
self.__name = "warn"
def handle(self, level, msg):
if level == self.__name:
print('WARN: ', msg)
return
if self.next != None:
self.next.handle(level, msg)
class ErrorHandler(Handler):
def __init__(self):
super().__init__()
self.__name = "error"
def handle(self, level, msg):
if level == self.__name:
print('ERROR: ', msg)
return
if self.next != None:
self.next.handle(level, msg)
# 以下是測試程式碼
log_handler = LogHandler()
warn_handler = WarnHandler()
error_handler = ErrorHandler()
# 設定下一個處理的節點
log_handler.set_next(warn_handler)
warn_handler.set_next(error_handler)
log_handler.handle("error", "Some error occur")
複製程式碼
4. 參考
- 《JavaScript 設計模式和開發實踐》
- javascript 之 責任鏈模式
- 職責鏈模式
5. ?部落格軟廣?
個人技術部落格-godbmw.com 歡迎來玩! 每週至少 1 篇原創技術分享,還有開源教程(webpack、設計模式)、面試刷題(偏前端)、知識整理(每週零碎),歡迎長期關注!本篇部落格地址是:《每天一個設計模式之責任鏈模式》。
如果您也想嘗試知識整理 + 搭建功能完善/設計簡約/快速啟動的個人部落格,請直接戳theme-bmw