責(zé)任鏈模式

定義

為了避免請求發(fā)送者與接收者耦合在一起诫钓,讓多個對象都有可能接收請求幔睬,將這些對象連接成一條鏈,并且沿著這條鏈傳遞請求旧噪,直到有對象處理它為止,職責(zé)鏈模式又稱為責(zé)任鏈模式吨娜,它是一種對象行為型模式。(如果你接觸過異常處理淘钟,那么套用異常處理機制可以更好地理解)宦赠。

職責(zé)鏈可以是一條直線,也可以是一個環(huán),還可以是一個樹形結(jié)構(gòu)米母,不過最常見的職責(zé)鏈是直線型勾扭,即沿著一條單向的鏈來傳遞請求。鏈上的每一個對象都是請求處理者铁瞒,職責(zé)鏈模式可以將請求的處理者組織成一條鏈妙色,并使請求沿著鏈傳遞,由鏈上的處理者對請求進行相應(yīng)的處理慧耍,而客戶端無須關(guān)心請求的處理細節(jié)以及請求的傳遞身辨,只需將請求發(fā)送到鏈上即可丐谋,通過這種方法將請求的發(fā)送者和請求的處理者解耦,消除兩個角色間的依賴關(guān)系煌珊,可以自由地組合号俐。

原理結(jié)構(gòu)

上圖闡釋的是職責(zé)連模式的實現(xiàn)原理,主要角色包括:

Handler:抽象處理者定庵。定義出一個處理請求的接口吏饿。如果需要,接口可以定義出一個方法洗贰,以設(shè)定和返回對下家的引用找岖。這個角色通常由一個抽象類或接口實現(xiàn)。

ConcreteHandler: 具體處理者敛滋。具體處理者接到請求后许布,可以選擇將請求處理掉,或者將請求傳給下家绎晃。由于具體處理者持有對下家的引用蜜唾,因此,如果需要庶艾,具體處理者可以訪問下家袁余。

Client:客戶端

handleRequest:抽象處理者的公用接口,要求每個鏈式節(jié)點都實現(xiàn)這個接口咱揍,能夠處理客戶端發(fā)過來的請求數(shù)據(jù)颖榜。

對于每個鏈式節(jié)點,需要滿足一下兩個條件:

實現(xiàn)抽象處理者(Handler)所定義的抽象接口煤裙,能夠識別接收的請求掩完;

有一個successor,用于把當前不能處理的請求轉(zhuǎn)發(fā)傳遞到下一個節(jié)點硼砰,如此才能形成一個鏈且蓬。(successor是指下一個ConcreteHandler的引用,相當于鏈表里面的next指針)

由于通過上述的編程設(shè)計题翰,使得請求和處理該請求的對象完全沒有依賴關(guān)系恶阴,因為客戶端甚至不知道是誰處理了這個請求,這樣的話豹障,使得整個鏈式結(jié)構(gòu)很靈活冯事,可以隨時添加新的的節(jié)點,當然也支持隨意調(diào)節(jié)節(jié)點順序血公、刪除不必要的節(jié)點等等操作桅咆。

iOS實現(xiàn)

職責(zé)鏈模式的一個很重要的特點是,當客戶發(fā)出請求之后坞笙,客戶端并不知道哪一個對象最終處理這個請求岩饼,這樣系統(tǒng)的更改可以在不影響客戶端的情況下動態(tài)地重新組織和分配責(zé)任。

下面給出類結(jié)構(gòu)圖薛夜。

從上圖可以看出籍茧,當客戶提交一個請求時,請求是沿鏈傳遞直至有一個ConcreteHandler對象負責(zé)處理它梯澜。這樣做的好處是請求者不用管哪個對象來處理寞冯,反正最終是要被某一個對象處理就是了。也就是說接收者和發(fā)送者都沒有對方的明確信息晚伙,且鏈中的對象自己也不知道鏈的結(jié)構(gòu)吮龄。結(jié)果是職責(zé)鏈可簡化對象的相互連接,它們僅需保持一個指向其后繼者的引用咆疗,而不需保持它所有的候選接受者的引用漓帚。

這些特點的好處是我們可以隨時增加或修改處理一個請求的結(jié)構(gòu)。增強了給對象指派職責(zé)的靈活性午磁。但是尝抖,一個請求極有可能到了鏈的末端都得不到處理,或者因為沒有正確配置而得不到處理迅皇,所以這更需要我們事先考慮全面昧辽。

好的,說了這么多登颓,還是老樣子搅荞,給大家展示一下簡單的示意代碼。

注意:本文所有代碼均在ARC環(huán)境下編譯通過框咙。

Handlers類接口

復(fù)制代碼代碼如下:

#import

@interface Handlers :NSObject{

Handlers *mySuccessor;

}

-(void)SetSuccessor:(Handlers*)successor;

-(void)HandleRequest:(int)request;

@end

Handlers類實現(xiàn)

復(fù)制代碼代碼如下:

#import "Handlers.h"

@implementation Handlers

-(void)SetSuccessor:(Handlers *)successor{

mySuccessor = successor;

}

-(void)HandleRequest:(int)request{

return;

}

@end

ConcreteHandler1類接口

復(fù)制代碼代碼如下:

#import "Handlers.h"

@interface ConcreteHandler1:Handlers

-(void)HandleRequest:(int)request;

@end

ConcreteHandler1類實現(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類接口

復(fù)制代碼代碼如下:

#import "Handlers.h"

@interface ConcreteHandler2 :Handlers

@end

ConcreteHandler2類實現(xiàn)

復(fù)制代碼代碼如下:

#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類接口

復(fù)制代碼代碼如下:

#import "Handlers.h"

@interface ConcreteHandler3 :Handlers

@end

ConcreteHandler3類實現(xiàn)

復(fù)制代碼代碼如下:

#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)用

復(fù)制代碼代碼如下:

#import

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é)

行為型模式是對在不同的對象之間劃分責(zé)任和算法的抽象化暇检,行為型模式不僅僅關(guān)注類和對象的結(jié)構(gòu),而且重點關(guān)注它們之間的相互作用婉称。通過行為型模式块仆,可以更加清晰地劃分類與對象的職責(zé),并研究系統(tǒng)在運行時實例對象之間的交互王暗。行為型模式可以分為類行為型模式和對象行為型模式兩種悔据。職責(zé)鏈模式可以避免請求發(fā)送者與接收者耦合在一起,讓多個對象都有可能接收請求俗壹,將這些對象連接成一條鏈科汗,并且沿著這條鏈傳遞請求,直到有對象處理它為止绷雏,它是一種對象行為型模式头滔。

在我們?nèi)粘J褂弥欣鹎猓覀兓蛟S直接接觸這方面的機會不多盒至,但是,如果你認真有研究過程序的一場處理機制,那么你就能夠發(fā)現(xiàn)這種處理機制正是采用職責(zé)鏈的方式處理程序中拋出的異常錯誤的箫措。

在職責(zé)鏈模式里学搜,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈娃豹。請求在這個鏈上傳遞憔涉,直到鏈上的某一個對象決定處理此請求。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求箭跳,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織鏈和分配責(zé)任晨另。

職責(zé)鏈模式的主要優(yōu)點在于可以降低系統(tǒng)的耦合度,簡化對象的相互連接谱姓,同時增強給對象指派職責(zé)的靈活性借尿,增加新的請求處理類也很方便;其主要缺點在于不能保證請求一定被接收逝段,且對于比較長的職責(zé)鏈垛玻,請求的處理可能涉及到多個處理對象,系統(tǒng)性能將受到一定影響奶躯,而且在進行代碼調(diào)試時不太方便帚桩。

優(yōu)點:

降低耦合度。

可簡化對象的相互連接嘹黔。

增強給對象指派職責(zé)的靈活性账嚎。

增加新的請求處理類很方便。

缺點:

不能保證請求一定被接收儡蔓。

系統(tǒng)性能將受到一定影響郭蕉,而且在進行代碼調(diào)試時不太方便(可能會造成循環(huán)調(diào)用)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喂江,一起剝皮案震驚了整個濱河市召锈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌获询,老刑警劉巖涨岁,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吉嚣,居然都是意外死亡梢薪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門尝哆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秉撇,“玉大人,你說我怎么就攤上這事∷龉荩” “怎么了规阀?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長啡捶。 經(jīng)常有香客問我姥敛,道長,這世上最難降的妖魔是什么瞎暑? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮与帆,結(jié)果婚禮上了赌,老公的妹妹穿的比我還像新娘。我一直安慰自己玄糟,他們只是感情好勿她,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阵翎,像睡著了一般逢并。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上郭卫,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天砍聊,我揣著相機與錄音,去河邊找鬼贰军。 笑死玻蝌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的词疼。 我是一名探鬼主播俯树,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贰盗!你這毒婦竟也來了许饿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤舵盈,失蹤者是張志新(化名)和其女友劉穎陋率,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體书释,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡翘贮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了爆惧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狸页。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芍耘,到底是詐尸還是另有隱情址遇,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布斋竞,位于F島的核電站倔约,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坝初。R本人自食惡果不足惜浸剩,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鳄袍。 院中可真熱鬧绢要,春花似錦、人聲如沸拗小。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哀九。三九已至剿配,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阅束,已是汗流浹背呼胚。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留围俘,地道東北人砸讳。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像界牡,于是被迫代替她去往敵國和親簿寂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1 場景問題# 1.1 申請聚餐費用## 來考慮這樣一個功能:申請聚餐費用的管理宿亡。 很多公司都有這樣的福利常遂,就是項...
    七寸知架構(gòu)閱讀 3,118評論 3 58
  • 源碼地址 介紹 它是一種行為型設(shè)計模式之一。它的每一個節(jié)點都可以看作是一個對象挽荠,每一個對象擁有不同的處理邏輯克胳,將一...
    yangMr閱讀 723評論 0 3
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是責(zé)任鏈模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 純與不純的責(zé)任鏈模式 優(yōu)點和缺點 ...
    w1992wishes閱讀 1,252評論 4 14
  • 被別人問到,自己只知道這個名字圈匆,但是完全不知道內(nèi)容漠另,竟然還是這么常用的設(shè)計的模式,丟人啊跃赚,然后找到一篇笆搓,介紹簡單好...
    壹人城閱讀 1,145評論 0 7
  • 對我而言性湿,你是我信仰一般的存在,我不知為什么說出這樣的話满败,可能天性使然吧肤频!你那樣平凡,在我看來并沒有什么優(yōu)點可言...
    你的名字Y我的故事閱讀 172評論 0 0