定義
責任鏈模式:使多個對象都有機會處理請求胜嗓,從而避免了請求的發(fā)送者和接受者之間的耦合關系伏社。將這些對象連成一條鏈短条,并沿著這條鏈傳遞該請求岩四,直到有對象處理它為止恭朗。
責任鏈模式的重點是在“鏈”上屏镊,有一條鏈去處理相似的請求,在鏈中決定誰來處理這個請求痰腮,并返回相應的結(jié)果而芥。
類圖
Handle是上層抽象類,定義handleRequest方法(處理他知道如何讓處理的請求對象)膀值。Handle有一個指向另一個同類型實例的引用棍丐,即successor。當調(diào)用Handler實例的handleRequest方法不知道如何處理請求時沧踏,它會用同樣的方法把請求轉(zhuǎn)發(fā)給successor歌逢,一直如此,直到傳給鏈中的最后一個Handler
ConcreteHandler1和ConcreteHandler2實現(xiàn)了handleRequest方法(處理他們認識的請求對象)翘狱。
看一個形象點的圖
就好比如上圖:由發(fā)送者發(fā)起請求秘案,由具體的接受者處理該請求,先是一級接受者進行處理潦匈,如果它能夠處理就直接處理請求阱高,如果不能處理就傳遞到二級接受者,二級接受者同樣看是否自己能夠處理該請求茬缩,如果能夠處理就執(zhí)行不能處理就傳遞給下一級赤惊。
跟我們平時開發(fā)找誰解決bug是一樣的,比如:團隊中有3個 iOS開發(fā)人員(ABC) 寒屯,測試人員發(fā)現(xiàn)了一個 bug 荐捻,然后先問A:“能不能處理這個 bug黍少?” 而 A 表示:“我并不負責這一部分的內(nèi)容,你可以去問一下 B” 处面,接著測試人員就去問了B 厂置,B 也表示他不負責這塊,并讓測試去找C魂角,此時 C 表示他可以處理昵济,則責任到此結(jié)束。
iOS中責任鏈的使用
iOS中有許多情況使用到了責任鏈模式野揪,最典型的就是響應鏈访忿,一層層的往下傳遞事件,尋找可以處理事件的對象斯稳。
DEMO
公司處理人員申請經(jīng)費流程海铆,包括員工、經(jīng)理挣惰、CEO卧斟。首先定義經(jīng)費類和鏈式傳遞協(xié)議
// 鏈式協(xié)議
protocol Chain {
var nextManagementLevel: Chain { get set } // 傳遞責任
func shouldApproveExpenditure(expenditure: Expenditure)
}
// 經(jīng)費
class Expenditure {
private var _amount: Int = 0
var amount: Int { // 金額
get {
return _amount
}
set {
_amount = newValue
}
}
init(amount: Int) {
self.amout = amout
}
}
具體處理申請流程者
// 員工
class Employee: Chain {
private var _nextManagementLevel: Chain?
var nextManagementLevel: Chain {
set {
_nextManagementLevel = newValue
}
get {
return _nextManagementLevel!
}
}
func shouldApproveExpenditure(expenditure: Expenditure) {
if expenditure.amount > 0 && expenditure.amount < 100 {
print("An exployee can approve this expenditure")
} else {
if _nextManagementLevel != nil {
nextManagementLevel.shouldApproveExpenditure(expenditure: expenditure)
}
}
}
}
// 經(jīng)理
class Manager: Chain {
private var _nextManagementLevel: Chain?
var nextManagementLevel: Chain {
set {
_nextManagementLevel = newValue
}
get {
return _nextManagementLevel!
}
}
func shouldApproveExpenditure(expenditure: Expenditure) {
if expenditure.amount > 101 && expenditure.amount < 1000 {
print("Your manager can approve this expenditure")
} else {
if _nextManagementLevel != nil {
nextManagementLevel.shouldApproveExpenditure(expenditure: expenditure)
}
}
}
}
// CEO
class CEO: Chain {
private var _nextManagementLevel: Chain?
var nextManagementLevel: Chain {
set {
_nextManagementLevel = newValue
}
get {
return _nextManagementLevel!
}
}
func shouldApproveExpenditure(expenditure: Expenditure) {
if expenditure.amount > 1001 && expenditure.amount < 10000 {
print("The CEO can approve this expenditure")
} else {
print("This expenditure is too large and won't be approved")
}
}
}
使用
override func viewDidLoad() {
super.viewDidLoad()
// 創(chuàng)建執(zhí)行者
let employee = Employee()
let manager = Manager()
let ceo = CEO()
// 下一個處理者
employee.nextManagementLevel = manager
manager.nextManagementLevel = ceo
// 申請經(jīng)費
let expenditure = Expenditure(amount: 5)
employee.shouldApproveExpenditure(expenditure: expenditure)
// 修改申請金額
expenditure.amount = 500
employee.shouldApproveExpenditure(expenditure: expenditure)
expenditure.amount = 5000
employee.shouldApproveExpenditure(expenditure: expenditure)
expenditure.amount = 50000
employee.shouldApproveExpenditure(expenditure: expenditure)
}
運行輸出
An exployee can approve this expenditure
Your boss can approve this expenditure
The CEO can approve this expenditure
This expenditure is too large and won't be approved
使用場景
- 有多個對象可以處理同一個請求,動態(tài)確定誰可以處理該請求
- 不明確指定接受者的情況下憎茂,給多個對象中的其中一個對象發(fā)送請求
- 動態(tài)指定一組對象實現(xiàn)請求
雖然說責任鏈一般是指當一個對象可以處理時候停止傳遞珍语,但是在有需求的時候,就算不停止傳遞也沒有關系竖幔。
優(yōu)缺點
優(yōu)點
責任鏈模式非常顯著的優(yōu)點是將請求和處理分開板乙。請求者可以不用知道是誰處理的,處理者可以不用知道請求的全貌拳氢,兩者解耦募逞,提高系統(tǒng)的靈活性。
缺點
責任鏈模式有兩個非常顯著的缺點:一是性能問題饿幅,每個請求都是從鏈頭遍歷到鏈尾凡辱,特別是在鏈比較長的時候,性能是一共非常大的問題栗恩。二是調(diào)試不方便,特別是鏈條比較長洪燥,環(huán)節(jié)比較多的時候磕秤,由于采用了類似遞歸的方式,調(diào)試的時候邏輯可能比較復雜