iOS應(yīng)用設(shè)計(jì)模式開(kāi)發(fā)中職責(zé)鏈(責(zé)任鏈)模式的實(shí)現(xiàn)解析
定義
為了避免請(qǐng)求發(fā)送者與接收者耦合在一起,讓多個(gè)對(duì)象都有可能接收請(qǐng)求,將這些對(duì)象連接成一條鏈,并且沿著這條鏈傳遞請(qǐng)求,直到有對(duì)象處理它為止,職責(zé)鏈模式又稱(chēng)為責(zé)任鏈模式,它是一種對(duì)象行為型模式。(如果你接觸過(guò)異常處理,那么套用異常處理機(jī)制可以更好地理解)。
職責(zé)鏈可以是一條直線(xiàn),也可以是一個(gè)環(huán),還可以是一個(gè)樹(shù)形結(jié)構(gòu),不過(guò)最常見(jiàn)的職責(zé)鏈?zhǔn)侵本€(xiàn)型,即沿著一條單向的鏈來(lái)傳遞請(qǐng)求。鏈上的每一個(gè)對(duì)象都是請(qǐng)求處理者,職責(zé)鏈模式可以將請(qǐng)求的處理者組織成一條鏈,并使請(qǐng)求沿著鏈傳遞,由鏈上的處理者對(duì)請(qǐng)求進(jìn)行相應(yīng)的處理,而客戶(hù)端無(wú)須關(guān)心請(qǐng)求的處理細(xì)節(jié)以及請(qǐng)求的傳遞,只需將請(qǐng)求發(fā)送到鏈上即可,通過(guò)這種方法將請(qǐng)求的發(fā)送者和請(qǐng)求的處理者解耦,消除兩個(gè)角色間的依賴(lài)關(guān)系,可以自由地組合。
原理結(jié)構(gòu)

上圖闡釋的是職責(zé)連模式的實(shí)現(xiàn)原理,主要角色包括:
Handler:抽象處理者。定義出一個(gè)處理請(qǐng)求的接口。如果需要,接口可以定義出一個(gè)方法,以設(shè)定和返回對(duì)下家的引用。這個(gè)角色通常由一個(gè)抽象類(lèi)或接口實(shí)現(xiàn)。
ConcreteHandler: 具體處理者。具體處理者接到請(qǐng)求后,可以選擇將請(qǐng)求處理掉,或者將請(qǐng)求傳給下家。由于具體處理者持有對(duì)下家的引用,因此,如果需要,具體處理者可以訪(fǎng)問(wèn)下家。
Client:客戶(hù)端
handleRequest:抽象處理者的公用接口,要求每個(gè)鏈?zhǔn)焦?jié)點(diǎn)都實(shí)現(xiàn)這個(gè)接口,能夠處理客戶(hù)端發(fā)過(guò)來(lái)的請(qǐng)求數(shù)據(jù)。
對(duì)于每個(gè)鏈?zhǔn)焦?jié)點(diǎn),需要滿(mǎn)足一下兩個(gè)條件:
實(shí)現(xiàn)抽象處理者(Handler)所定義的抽象接口,能夠識(shí)別接收的請(qǐng)求;
有一個(gè)successor,用于把當(dāng)前不能處理的請(qǐng)求轉(zhuǎn)發(fā)傳遞到下一個(gè)節(jié)點(diǎn),如此才能形成一個(gè)鏈。(successor是指下一個(gè)ConcreteHandler的引用,相當(dāng)于鏈表里面的next指針)
由于通過(guò)上述的編程設(shè)計(jì),使得請(qǐng)求和處理該請(qǐng)求的對(duì)象完全沒(méi)有依賴(lài)關(guān)系,因?yàn)榭蛻?hù)端甚至不知道是誰(shuí)處理了這個(gè)請(qǐng)求,這樣的話(huà),使得整個(gè)鏈?zhǔn)浇Y(jié)構(gòu)很靈活,可以隨時(shí)添加新的的節(jié)點(diǎn),當(dāng)然也支持隨意調(diào)節(jié)節(jié)點(diǎn)順序、刪除不必要的節(jié)點(diǎn)等等操作。
iOS實(shí)現(xiàn)
職責(zé)鏈模式的一個(gè)很重要的特點(diǎn)是,當(dāng)客戶(hù)發(fā)出請(qǐng)求之后,客戶(hù)端并不知道哪一個(gè)對(duì)象最終處理這個(gè)請(qǐng)求,這樣系統(tǒng)的更改可以在不影響客戶(hù)端的情況下動(dòng)態(tài)地重新組織和分配責(zé)任。
下面給出類(lèi)結(jié)構(gòu)圖。

從上圖可以看出,當(dāng)客戶(hù)提交一個(gè)請(qǐng)求時(shí),請(qǐng)求是沿鏈傳遞直至有一個(gè)ConcreteHandler對(duì)象負(fù)責(zé)處理它。這樣做的好處是請(qǐng)求者不用管哪個(gè)對(duì)象來(lái)處理,反正最終是要被某一個(gè)對(duì)象處理就是了。也就是說(shuō)接收者和發(fā)送者都沒(méi)有對(duì)方的明確信息,且鏈中的對(duì)象自己也不知道鏈的結(jié)構(gòu)。結(jié)果是職責(zé)鏈可簡(jiǎn)化對(duì)象的相互連接,它們僅需保持一個(gè)指向其后繼者的引用,而不需保持它所有的候選接受者的引用。
這些特點(diǎn)的好處是我們可以隨時(shí)增加或修改處理一個(gè)請(qǐng)求的結(jié)構(gòu)。增強(qiáng)了給對(duì)象指派職責(zé)的靈活性。但是,一個(gè)請(qǐng)求極有可能到了鏈的末端都得不到處理,或者因?yàn)闆](méi)有正確配置而得不到處理,所以這更需要我們事先考慮全面。
好的,說(shuō)了這么多,還是老樣子,給大家展示一下簡(jiǎn)單的示意代碼。
注意:本文所有代碼均在A(yíng)RC環(huán)境下編譯通過(guò)。
Handlers類(lèi)接口
#import <Foundation/Foundation.h>
@interface Handlers :NSObject{
Handlers *mySuccessor;
}
-(void)SetSuccessor:(Handlers*)successor;
-(void)HandleRequest:(int)request;
@end
Handlers類(lèi)實(shí)現(xiàn)
#import "Handlers.h"
@implementation Handlers
-(void)SetSuccessor:(Handlers *)successor{
mySuccessor = successor;
}
-(void)HandleRequest:(int)request{
return;
}
@end
ConcreteHandler1類(lèi)接口
#import "Handlers.h"
@interface ConcreteHandler1:Handlers
-(void)HandleRequest:(int)request;
@end
ConcreteHandler1類(lèi)實(shí)現(xiàn)
#import "ConcreteHandler1.h"
@implementation ConcreteHandler1
-(void)HandleRequest:(int)request{
if (request >=0 && request <10) {
NSLog(@"ConcreteHandler1處理%d", request);
}
else if (mySuccessor !=nil) {
[mySuccessor HandleRequest:request];
}
}
@end
ConcreteHandler2類(lèi)接口
#import "Handlers.h"
@interface ConcreteHandler2 :Handlers
@end
ConcreteHandler2類(lèi)實(shí)現(xiàn)
#import "ConcreteHandler2.h"
@implementation ConcreteHandler2
-(void)HandleRequest:(int)request{
if (request >=10 && request <20) {
NSLog(@"ConcreteHandler2處理%d", request);
}
else if(mySuccessor !=nil) {
[mySuccessor HandleRequest:request];
}
}
@end
ConcreteHandler3類(lèi)接口
#import "Handlers.h"
@interface ConcreteHandler3 :Handlers
@end
ConcreteHandler3類(lèi)實(shí)現(xiàn)
#import "ConcreteHandler3.h"
@implementation ConcreteHandler3
-(void)HandleRequest:(int)request{
if (request >=20 && request <30) {
NSLog(@"ConcreteHandler3處理%d", request);
}
else if (mySuccessor !=nil) {
[mySuccessor HandleRequest:request];
}
}
@end
Main方法調(diào)用
#import <Foundation/Foundation.h>
int main(int argc,const char * argv[])
{
@autoreleasepool{
Handlers *h1 = [[ConcreteHandler1 alloc]init];
Handlers *h2 = [[ConcreteHandler2 alloc]init];
Handlers *h3 = [[ConcreteHandler3 alloc]init];
[h1 SetSuccessor:h2];
[h2 SetSuccessor:h3];
int requests[] = {2,5,14,22,18,3,27,20};
for (int i =0; i <8; i++) {
[h1 HandleRequest:requests[i]];
}
}
return 0;
}
好啦,代碼展示完畢!收工!
小結(jié)
行為型模式是對(duì)在不同的對(duì)象之間劃分責(zé)任和算法的抽象化,行為型模式不僅僅關(guān)注類(lèi)和對(duì)象的結(jié)構(gòu),而且重點(diǎn)關(guān)注它們之間的相互作用。通過(guò)行為型模式,可以更加清晰地劃分類(lèi)與對(duì)象的職責(zé),并研究系統(tǒng)在運(yùn)行時(shí)實(shí)例對(duì)象之間的交互。行為型模式可以分為類(lèi)行為型模式和對(duì)象行為型模式兩種。職責(zé)鏈模式可以避免請(qǐng)求發(fā)送者與接收者耦合在一起,讓多個(gè)對(duì)象都有可能接收請(qǐng)求,將這些對(duì)象連接成一條鏈,并且沿著這條鏈傳遞請(qǐng)求,直到有對(duì)象處理它為止,它是一種對(duì)象行為型模式。
在我們?nèi)粘J褂弥?,我們或許直接接觸這方面的機(jī)會(huì)不多,但是,如果你認(rèn)真有研究過(guò)程序的一場(chǎng)處理機(jī)制,那么你就能夠發(fā)現(xiàn)這種處理機(jī)制正是采用職責(zé)鏈的方式處理程序中拋出的異常錯(cuò)誤的。
在職責(zé)鏈模式里,很多對(duì)象由每一個(gè)對(duì)象對(duì)其下家的引用而連接起來(lái)形成一條鏈。請(qǐng)求在這個(gè)鏈上傳遞,直到鏈上的某一個(gè)對(duì)象決定處理此請(qǐng)求。發(fā)出這個(gè)請(qǐng)求的客戶(hù)端并不知道鏈上的哪一個(gè)對(duì)象最終處理這個(gè)請(qǐng)求,這使得系統(tǒng)可以在不影響客戶(hù)端的情況下動(dòng)態(tài)地重新組織鏈和分配責(zé)任。
職責(zé)鏈模式的主要優(yōu)點(diǎn)在于可以降低系統(tǒng)的耦合度,簡(jiǎn)化對(duì)象的相互連接,同時(shí)增強(qiáng)給對(duì)象指派職責(zé)的靈活性,增加新的請(qǐng)求處理類(lèi)也很方便;其主要缺點(diǎn)在于不能保證請(qǐng)求一定被接收,且對(duì)于比較長(zhǎng)的職責(zé)鏈,請(qǐng)求的處理可能涉及到多個(gè)處理對(duì)象,系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時(shí)不太方便。
優(yōu)點(diǎn):
降低耦合度。
可簡(jiǎn)化對(duì)象的相互連接。
增強(qiáng)給對(duì)象指派職責(zé)的靈活性。
增加新的請(qǐng)求處理類(lèi)很方便。
缺點(diǎn):
不能保證請(qǐng)求一定被接收。
系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時(shí)不太方便(可能會(huì)造成循環(huán)調(diào)用)。
- iOS App設(shè)計(jì)模式開(kāi)發(fā)中對(duì)建造者模式的運(yùn)用實(shí)例
- iOS App設(shè)計(jì)模式開(kāi)發(fā)中對(duì)迭代器模式的使用示例
- iOS App的設(shè)計(jì)模式開(kāi)發(fā)中對(duì)State狀態(tài)模式的運(yùn)用
- 解析iOS應(yīng)用開(kāi)發(fā)中對(duì)設(shè)計(jì)模式中的抽象工廠(chǎng)模式的實(shí)現(xiàn)
- 詳解iOS應(yīng)用開(kāi)發(fā)中使用設(shè)計(jì)模式中的抽象工廠(chǎng)模式
- 實(shí)例解析設(shè)計(jì)模式中的外觀(guān)模式在iOS App開(kāi)發(fā)中的運(yùn)用
- 設(shè)計(jì)模式開(kāi)發(fā)中的備忘錄模式在iOS應(yīng)用開(kāi)發(fā)中的運(yùn)用實(shí)例
- 深入解析設(shè)計(jì)模式中的裝飾器模式在iOS應(yīng)用開(kāi)發(fā)中的實(shí)現(xiàn)
- iOS App設(shè)計(jì)模式開(kāi)發(fā)中策略模式的實(shí)現(xiàn)示例
- 詳解iOS App設(shè)計(jì)模式開(kāi)發(fā)中對(duì)于享元模式的運(yùn)用
相關(guān)文章
iOS開(kāi)發(fā)retina屏幕下的點(diǎn)與像素關(guān)系詳解
這篇文章主要為大家介紹了iOS開(kāi)發(fā)retina屏幕下的點(diǎn)與像素關(guān)系詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
總結(jié)適配IOS10開(kāi)發(fā)需要注意的問(wèn)題
本篇文章主要介紹了適配IOS10需要注意的問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧。2016-12-12
iOS逆向開(kāi)發(fā)之微信自動(dòng)添加好友功能
這篇文章主要介紹了iOS逆向開(kāi)發(fā)之微信自動(dòng)添加好友功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04
詳解IOS圖層轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了IOS圖層轉(zhuǎn)場(chǎng)動(dòng)畫(huà), CATransition類(lèi)實(shí)現(xiàn)層的轉(zhuǎn)場(chǎng)動(dòng)畫(huà),能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫(huà)效果,感興趣的小伙伴們可以參考一下2016-02-02
iOS SwiftUI 顏色漸變填充效果的實(shí)現(xiàn)
這篇文章主要介紹了iOS SwiftUI 顏色漸變填充效果的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
開(kāi)發(fā)繪圖、手勢(shì)綜合App注意點(diǎn)
本篇文章主要給大家詳細(xì)講述了在IOS開(kāi)發(fā)繪圖、手勢(shì)綜合App容易遇到的坑以及注意事項(xiàng)等內(nèi)容,有興趣的朋友參考下吧。2018-02-02
詳解iOS App中圖片的線(xiàn)段涂鴉功能的添加方法
這篇文章主要介紹了如何設(shè)計(jì)iOS App中圖片的線(xiàn)段涂鴉功能,也就是很多應(yīng)用中圖片上傳時(shí)帶有的編輯功能的基礎(chǔ),需要的朋友可以參考下2016-03-03
iOS CAReplicatorLayer實(shí)現(xiàn)脈沖動(dòng)畫(huà)效果
這篇文章主要介紹了iOS CAReplicatorLayer實(shí)現(xiàn)脈沖動(dòng)畫(huà)效果 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06

