設(shè)計(jì)模式| 行為型模式 (上)

前言

行為型模式共十一種:策略模式澈段、模板方法模式讼积、觀察者模式沐祷、迭代器模式、解釋器模式纵寝、責(zé)任鏈模式论寨、命令模式、備忘錄模式、狀態(tài)模式葬凳、訪問(wèn)者模式绰垂、中介者模式。
分兩篇文章總結(jié)火焰,本篇主要涉及到的設(shè)計(jì)模式是:

策略模式劲装、模板方法模式、觀察者模式荐健、迭代器模式、解釋器模式琳袄、責(zé)任鏈模式江场。

其他同系列的文章還有:
面向?qū)ο缶幊讨械牧笤瓌t
設(shè)計(jì)模式| 創(chuàng)建型模式
設(shè)計(jì)模式| 結(jié)構(gòu)型模式
設(shè)計(jì)模式| 行為型模式 (上)
設(shè)計(jì)模式| 行為型模式 (下)
歡迎閱讀,評(píng)論=讯骸V贩瘛!

1碎紊、策略模式

算法的封裝與切換-策略模式

生活中佑附,對(duì)一個(gè)問(wèn)題解決,有多種方案可以選擇仗考。比如出行旅游去某地音同,要選擇交通工具的問(wèn)題上。

- 如果沒(méi)有時(shí)間但是不在乎錢秃嗜,可以選擇坐飛機(jī)权均。
- 如果沒(méi)有錢,可以選擇坐大巴或者火車锅锨。
- 如果再窮一點(diǎn)叽赊,可以選擇騎自行車。

組織架構(gòu)好這些靈活多樣的算法(選擇)必搞,而且可以隨意互相替換必指。這種解決方案就是策略模式。

策略模式(Strategy Pattern):定義一系列算法類恕洲,將每一個(gè)算法封裝起來(lái)塔橡,并讓它們可以相互替換,策略模式讓算法獨(dú)立于使用它的客戶而變化霜第,也稱為政策模式(Policy)谱邪。策略模式是一種對(duì)象行為型模式。

 在策略模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
  ● Context(環(huán)境類):環(huán)境類是使用算法的角色庶诡,它在解決某個(gè)問(wèn)題(即實(shí)現(xiàn)某個(gè)方法)時(shí)可以采用多種策略惦银。
    在環(huán)境類中維持一個(gè)對(duì)抽象策略類的引用實(shí)例,用于定義所采用的策略。

  ● Strategy(抽象策略類):它為所支持的算法聲明了抽象方法扯俱,是所有策略類的父類书蚪,它可以是抽象類或具體類,也可以是接口迅栅。
    環(huán)境類通過(guò)抽象策略類中聲明的方法在運(yùn)行時(shí)調(diào)用具體策略類中實(shí)現(xiàn)的算法殊校。

  ● ConcreteStrategy(具體策略類):它實(shí)現(xiàn)了在抽象策略類中聲明的算法,在運(yùn)行時(shí)读存,
    具體策略類將覆蓋在環(huán)境類中定義的抽象策略類對(duì)象为流,使用一種具體的算法實(shí)現(xiàn)某個(gè)業(yè)務(wù)處理。

1.策略模式的優(yōu)缺點(diǎn)

策略模式的主要優(yōu)點(diǎn)有:

策略類之間可以自由切換让簿,由于策略類實(shí)現(xiàn)自同一個(gè)抽象敬察,所以他們之間可以自由切換。

易于擴(kuò)展尔当,增加一個(gè)新的策略對(duì)策略模式來(lái)說(shuō)非常容易莲祸,基本上可以在不改變?cè)写a的基礎(chǔ)上進(jìn)行擴(kuò)展。

避免使用多重條件椭迎,如果不使用策略模式锐帜,對(duì)于所有的算法,必須使用條件語(yǔ)句進(jìn)行連接畜号,通過(guò)條件判斷來(lái)決定使用哪一種算法缴阎,
在上一篇文章中我們已經(jīng)提到,使用多重條件判斷是非常不容易維護(hù)的简软。

2.策略模式的缺點(diǎn)主要有兩個(gè):

 維護(hù)各個(gè)策略類會(huì)給開(kāi)發(fā)帶來(lái)額外開(kāi)銷药蜻,可能大家在這方面都有經(jīng)驗(yàn):一般來(lái)說(shuō),策略類的數(shù)量超過(guò)5個(gè)替饿,就比較令人頭疼了语泽。

必須對(duì)客戶端(調(diào)用者)暴露所有的策略類,因?yàn)槭褂媚姆N策略是由客戶端來(lái)決定的视卢,
因此踱卵,客戶端應(yīng)該知道有什么策略,并且了解各種策略之間的區(qū)別据过,否則惋砂,后果很嚴(yán)重。
例如绳锅,有一個(gè)排序算法的策略模式西饵,提供了快速排序、冒泡排序鳞芙、選擇排序這三種算法眷柔,客戶端在使用這些算法之前期虾,
是不是先要明白這三種算法的適用情況?再比如驯嘱,客戶端要使用一個(gè)容器镶苞,有鏈表實(shí)現(xiàn)的,也有數(shù)組實(shí)現(xiàn)的鞠评,
客戶端是不是也要明白鏈表和數(shù)組有什么區(qū)別茂蚓?就這一點(diǎn)來(lái)說(shuō)是有悖于迪米特法則的。

適用場(chǎng)景

做面向?qū)ο笤O(shè)計(jì)的剃幌,對(duì)策略模式一定很熟悉聋涨,因?yàn)樗鼘?shí)質(zhì)上就是面向?qū)ο笾械睦^承和多態(tài),在看完策略模式的通用代碼后负乡,
我想牍白,即使之前從來(lái)沒(méi)有聽(tīng)說(shuō)過(guò)策略模式,在開(kāi)發(fā)過(guò)程中也一定使用過(guò)它吧敬鬓?至少在在以下兩種情況下淹朋,大家可以考慮使用策略模式笙各,

  A.幾個(gè)類的主要邏輯相同钉答,只在部分邏輯的算法和行為上稍有區(qū)別的情況。
  B.有幾種相似的行為杈抢,或者說(shuō)算法数尿,客戶端需要?jiǎng)討B(tài)地決定使用哪一種,那么可以使用策略模式惶楼,將這些算法封裝起來(lái)供客戶端調(diào)用右蹦。
   
策略模式是一種簡(jiǎn)單常用的模式,我們?cè)谶M(jìn)行開(kāi)發(fā)的時(shí)候歼捐,會(huì)經(jīng)常有意無(wú)意地使用它何陆,一般來(lái)說(shuō),
策略模式不會(huì)單獨(dú)使用豹储,跟模版方法模式贷盲、工廠模式等混合使用的情況比較多。

2剥扣、模板方法模式

在現(xiàn)實(shí)生活中巩剖,很多事情都包含幾個(gè)實(shí)現(xiàn)步驟,例如請(qǐng)客吃飯钠怯,無(wú)論吃什么佳魔,一般都包含點(diǎn)單、吃東西晦炊、買單等幾個(gè)步驟鞠鲜,
通常情況下這幾個(gè)步驟的次序是:點(diǎn)單 --> 吃東西 --> 買單宁脊。在這三個(gè)步驟中,點(diǎn)單和買單大同小異镊尺,
最大的區(qū)別在于第二步——吃什么朦佩?吃面條和吃滿漢全席可大不相同,

在軟件開(kāi)發(fā)中庐氮,有時(shí)也會(huì)遇到類似的情況语稠,某個(gè)方法的實(shí)現(xiàn)需要多個(gè)步驟(類似“請(qǐng)客”),其中有些步驟是固定的(類似“點(diǎn)單”和“買單”)
而有些步驟并不固定弄砍,存在可變性(類似“吃東西”)仙畦。為了提高代碼的復(fù)用性和系統(tǒng)的靈活性,
可以使用一種稱之為模板方法模式的設(shè)計(jì)模式來(lái)對(duì)這類情況進(jìn)行設(shè)計(jì)音婶,
在模板方法模式中慨畸,將實(shí)現(xiàn)功能的每一個(gè)步驟所對(duì)應(yīng)的方法稱為基本方法(例如“點(diǎn)單”、“吃東西”和“買單”)衣式,
而調(diào)用這些基本方法同時(shí)定義基本方法的執(zhí)行次序的方法稱為模板方法(例如“請(qǐng)客”)寸士。

在模板方法模式中,可以將相同的代碼放在父類中碴卧,例如將模板方法“請(qǐng)客”以及基本方法“點(diǎn)單”和“買單”的實(shí)現(xiàn)放在父類中弱卡,而對(duì)于基本方法“吃東西”,在父類中只做一個(gè)聲明住册,將其具體實(shí)現(xiàn)放在不同的子類中婶博,

在一個(gè)子類中提供“吃面條”的實(shí)現(xiàn),而另一個(gè)子類提供“吃滿漢全席”的實(shí)現(xiàn)荧飞。
通過(guò)使用模板方法模式凡人,一方面提高了代碼的復(fù)用性,另一方面還可以利用面向?qū)ο蟮亩鄳B(tài)性叹阔,在運(yùn)行時(shí)選擇一種具體子類挠轴,
實(shí)現(xiàn)完整的“請(qǐng)客”方法,提高系統(tǒng)的靈活性和可擴(kuò)展性耳幢。

模板方法模式:定義一個(gè)操作中算法的框架岸晦,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟帅掘。

  大部分剛步入職場(chǎng)的畢業(yè)生應(yīng)該都有類似這樣的經(jīng)歷委煤。一個(gè)復(fù)雜的任務(wù),
  由公司中的牛人們將主要的邏輯寫好修档,然后把那些看上去比較簡(jiǎn)單的方法寫成抽象的碧绞,交給其他的同事去開(kāi)發(fā)。
  這種分工方式在編程人員水平層次比較明顯的公司中經(jīng)常用到吱窝。
  比如一個(gè)項(xiàng)目組讥邻,有架構(gòu)師迫靖,高級(jí)工程師,初級(jí)工程師兴使,則一般由架構(gòu)師使用大量的接口系宜、抽象類將整個(gè)系統(tǒng)的邏輯串起來(lái),
  實(shí)現(xiàn)的編碼則根據(jù)難度的不同分別交給高級(jí)工程師和初級(jí)工程師來(lái)完成发魄。這就是典型的用到了模版方法模式盹牧。

模版方法模式的結(jié)構(gòu)

 模版方法模式由一個(gè)抽象類和一個(gè)(或一組)實(shí)現(xiàn)類通過(guò)繼承結(jié)構(gòu)組成,抽象類中的方法分為三種:

 1. 抽象方法:父類中只聲明但不加以實(shí)現(xiàn)励幼,而是定義好規(guī)范汰寓,然后由它的子類去實(shí)現(xiàn)。
 2.  模版方法:由抽象類聲明并加以實(shí)現(xiàn)苹粟。一般來(lái)說(shuō)有滑,模版方法調(diào)用抽象方法來(lái)完成主要的邏輯功能,
            并且模版方法大多會(huì)定義為final類型嵌削,指明主要的邏輯功能在子類中不能被重寫毛好。
 3. 鉤子方法:由抽象類聲明并加以實(shí)現(xiàn)。但是子類可以去擴(kuò)展苛秕,子類可以通過(guò)擴(kuò)展鉤子方法來(lái)影響模版方法的邏輯肌访。

 抽象類的任務(wù)是搭建邏輯的框架,通常由經(jīng)驗(yàn)豐富的人員編寫想帅,因?yàn)槌橄箢惖暮脡闹苯記Q定了程序是否穩(wěn)定性场靴。
 實(shí)現(xiàn)類用來(lái)實(shí)現(xiàn)細(xì)節(jié)啡莉。抽象類中的模版方法正是通過(guò)實(shí)現(xiàn)類擴(kuò)展的方法來(lái)完成業(yè)務(wù)邏輯港准。只要實(shí)現(xiàn)類中的擴(kuò)展方法通過(guò)了單元測(cè)試,
 在模版方法正確的前提下咧欣,整體功能一般不會(huì)出現(xiàn)大的錯(cuò)誤浅缸。

模版方法的優(yōu)點(diǎn)及適用場(chǎng)景

 容易擴(kuò)展。一般來(lái)說(shuō)魄咕,抽象類中的模版方法是不易反生改變的部分衩椒,而抽象方法是容易反生變化的部分,
 因此通過(guò)增加實(shí)現(xiàn)類一般可以很容易實(shí)現(xiàn)功能的擴(kuò)展哮兰,符合開(kāi)閉原則毛萌。

 便于維護(hù)。對(duì)于模版方法模式來(lái)說(shuō)喝滞,正是由于他們的主要邏輯相同阁将,才使用了模版方法,假如不使用模版方法右遭,
 任由這些相同的代碼散亂的分布在不同的類中做盅,維護(hù)起來(lái)是非常不方便的缤削。

 比較靈活。因?yàn)橛秀^子方法吹榴,因此亭敢,子類的實(shí)現(xiàn)也可以影響父類中主邏輯的運(yùn)行。
 但是图筹,在靈活的同時(shí)帅刀,由于子類影響到了父類,違反了里氏替換原則远剩,也會(huì)給程序帶來(lái)風(fēng)險(xiǎn)劝篷。這就對(duì)抽象類的設(shè)計(jì)有了更高的要求。

 在多個(gè)子類擁有相同的方法民宿,并且這些方法邏輯相同時(shí)娇妓,可以考慮使用模版方法模式。
 在程序的主框架相同活鹰,細(xì)節(jié)不同的場(chǎng)合下哈恰,也比較適合使用這種模式。

3志群、觀察者模式

對(duì)象間的聯(lián)動(dòng)—觀察者模式

觀察者模式是使用頻率最高的設(shè)計(jì)模式之一着绷,它用于建立一種對(duì)象與對(duì)象之間的依賴關(guān)系,
一個(gè)對(duì)象發(fā)生改變時(shí)將自動(dòng)通知其他對(duì)象锌云,其他對(duì)象將相應(yīng)作出反應(yīng)荠医。
在觀察者模式中,發(fā)生改變的對(duì)象稱為觀察目標(biāo)桑涎,而被通知的對(duì)象稱為觀察者彬向, 
一個(gè)觀察目標(biāo)可以對(duì)應(yīng)多個(gè)觀察者,而且這些觀察者之間可以沒(méi)有任何相互聯(lián)系攻冷,可以根據(jù)需要增加和刪除觀察者娃胆,使得系統(tǒng)更易于擴(kuò)展。

   觀察者模式定義如下:

觀察者模式(Observer Pattern):定義對(duì)象之間的一種一對(duì)多依賴關(guān)系等曼,使得每當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí)里烦,
其相關(guān)依賴對(duì)象皆得到通知并被自動(dòng)更新。
觀察者模式的別名包括發(fā)布-訂閱(Publish/Subscribe)模式禁谦、模型-視圖(Model/View)模式胁黑、
源-監(jiān)聽(tīng)器(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式是一種對(duì)象行為型模式州泊。

觀察者模式的結(jié)構(gòu)

在最基礎(chǔ)的觀察者模式中丧蘸,包括以下四個(gè)角色:

被觀察者:從類圖中可以看到,類中有一個(gè)用來(lái)存放觀察者對(duì)象的Vector容器(之所以使用Vector而不使用List拥诡,
        是因?yàn)槎嗑€程操作時(shí)触趴,Vector在是安全的氮发,而List則是不安全的),
        這個(gè)Vector容器是被觀察者類的核心冗懦,另外還有三個(gè)方法:attach方法是向這個(gè)容器中添加觀察者對(duì)象爽冕;
        detach方法是從容器中移除觀察者對(duì)象;notify方法是依次調(diào)用觀察者對(duì)象的對(duì)應(yīng)方法披蕉。這個(gè)角色可以是接口颈畸,
        也可以是抽象類或者具體的類,因?yàn)楹芏嗲闆r下會(huì)與其他的模式混用没讲,所以使用抽象類的情況比較多眯娱。

具體的被觀察者:使用這個(gè)角色是為了便于擴(kuò)展,可以在此角色中定義具體的業(yè)務(wù)邏輯爬凑。
觀察者:觀察者角色一般是一個(gè)接口徙缴,它只有一個(gè)update方法,在被觀察者狀態(tài)發(fā)生變化時(shí)嘁信,這個(gè)方法就會(huì)被觸發(fā)調(diào)用于样。
具體的觀察者:觀察者接口的具體實(shí)現(xiàn),在這個(gè)角色中潘靖,將定義被觀察者對(duì)象狀態(tài)發(fā)生變化時(shí)所要處理的邏輯穿剖。

觀察者模式的優(yōu)點(diǎn)

 觀察者與被觀察者之間是屬于輕度的關(guān)聯(lián)關(guān)系,并且是抽象耦合的卦溢,這樣糊余,對(duì)于兩者來(lái)說(shuō)都比較容易進(jìn)行擴(kuò)展。

 觀察者模式是一種常用的觸發(fā)機(jī)制单寂,它形成一條觸發(fā)鏈贬芥,依次對(duì)各個(gè)觀察者的方法進(jìn)行處理。但同時(shí)凄贩,這也算是觀察者模式一個(gè)缺點(diǎn)誓军,
 由于是鏈?zhǔn)接|發(fā)袱讹,當(dāng)觀察者比較多的時(shí)候疲扎,性能問(wèn)題是比較令人擔(dān)憂的。
 并且捷雕,在鏈?zhǔn)浇Y(jié)構(gòu)中椒丧,比較容易出現(xiàn)循環(huán)引用的錯(cuò)誤,造成系統(tǒng)假死救巷。

4壶熏、迭代器模式

遍歷聚合對(duì)象中的元素-迭代器模式

迭代器模式定義如下:

迭代器模式(Iterator Pattern):提供一種方法來(lái)訪問(wèn)聚合對(duì)象,而不用暴露這個(gè)對(duì)象的內(nèi)部表示浦译,其別名為游標(biāo)(Cursor)棒假。迭代器模式是一種對(duì)象行為型模式溯职。

 迭代器模式是一種使用頻率非常高的設(shè)計(jì)模式,
 通過(guò)引入迭代器可以將數(shù)據(jù)的遍歷功能從聚合對(duì)象中分離出來(lái)帽哑,聚合對(duì)象只負(fù)責(zé)存儲(chǔ)數(shù)據(jù)谜酒,而遍歷數(shù)據(jù)由迭代器來(lái)完成。
 由于很多編程語(yǔ)言的類庫(kù)都已經(jīng)實(shí)現(xiàn)了迭代器模式妻枕,因此在實(shí)際開(kāi)發(fā)中僻族,
 我們只需要直接使用Java、C#屡谐、OC等語(yǔ)言已定義好的迭代器即可述么,迭代器已經(jīng)成為我們操作聚合對(duì)象的基本工具之一。

iOS 迭代器:NSEnumerator

1愕掏、字典中的(有兩個(gè)方法):
  - (NSEnumerator<KeyType> *)keyEnumerator;//獲取所有key值
  - (NSEnumerator<ObjectType> *)objectEnumerator;//獲取所有value值

2度秘、數(shù)組中的(有兩個(gè)方法)
  - (NSEnumerator<ObjectType> *)objectEnumerator;//正向遍歷數(shù)組    ——>完全可用 for in 語(yǔ)法代替
  - (NSEnumerator<ObjectType> *)reverseObjectEnumerator;//反向遍歷數(shù)組
  1. 主要優(yōu)點(diǎn)

    迭代器模式的主要優(yōu)點(diǎn)如下:
    (1) 它支持以不同的方式遍歷一個(gè)聚合對(duì)象,在同一個(gè)聚合對(duì)象上可以定義多種遍歷方式饵撑。
        在迭代器模式中只需要用一個(gè)不同的迭代器來(lái)替換原有迭代器即可改變遍歷算法敷钾,
        我們也可以自己定義迭代器的子類以支持新的遍歷方式。
    
    (2) 迭代器簡(jiǎn)化了聚合類肄梨。由于引入了迭代器阻荒,在原有的聚合對(duì)象中不需要再自行提供數(shù)據(jù)遍歷等方法,這樣可以簡(jiǎn)化聚合類的設(shè)計(jì)众羡。
    
    (3) 在迭代器模式中侨赡,由于引入了抽象層,增加新的聚合類和迭代器類都很方便粱侣,無(wú)須修改原有代碼羊壹,滿足“開(kāi)閉原則”的要求。
    
  2. 主要缺點(diǎn)

    迭代器模式的主要缺點(diǎn)如下:
    (1)由于迭代器模式將存儲(chǔ)數(shù)據(jù)和遍歷數(shù)據(jù)的職責(zé)分離齐婴,增加新的聚合類需要對(duì)應(yīng)增加新的迭代器類油猫,類的個(gè)數(shù)成對(duì)增加,
       這在一定程度上增加了系統(tǒng)的復(fù)雜性柠偶。
    
    (2)抽象迭代器的設(shè)計(jì)難度較大情妖,需要充分考慮到系統(tǒng)將來(lái)的擴(kuò)展,例如JDK內(nèi)置迭代器Iterator就無(wú)法實(shí)現(xiàn)逆向遍歷诱担,
       如果需要實(shí)現(xiàn)逆向遍歷毡证,只能通過(guò)其子類ListIterator等來(lái)實(shí)現(xiàn),而ListIterator迭代器無(wú)法用于操作Set類型的聚合對(duì)象蔫仙。
       在自定義迭代器時(shí)料睛,創(chuàng)建一個(gè)考慮全面的抽象迭代器并不是件很容易的事情。
    
  3. 適用場(chǎng)景

    在以下情況下可以考慮使用迭代器模式:
    
    (1) 訪問(wèn)一個(gè)聚合對(duì)象的內(nèi)容而無(wú)須暴露它的內(nèi)部表示。將聚合對(duì)象的訪問(wèn)與內(nèi)部數(shù)據(jù)的存儲(chǔ)分離恤煞,
       使得訪問(wèn)聚合對(duì)象時(shí)無(wú)須了解其內(nèi)部實(shí)現(xiàn)細(xì)節(jié)屎勘。
    (2) 需要為一個(gè)聚合對(duì)象提供多種遍歷方式。
    (3) 為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口居扒,在該接口的實(shí)現(xiàn)類中為不同的聚合結(jié)構(gòu)提供不同的遍歷方式挑秉,
        而客戶端可以一致性地操作該接口。
    

5苔货、解釋器模式

自定義語(yǔ)言的實(shí)現(xiàn)—解釋器模式

解釋器模式介紹

解釋器模式:給定一個(gè)語(yǔ)言犀概,定義它的文法一種表示。并定義一個(gè)解釋器夜惭,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子姻灶。

也就是說(shuō),如果你想自己開(kāi)發(fā)一種語(yǔ)言來(lái)解釋執(zhí)行某些語(yǔ)言的特定語(yǔ)法诈茧,可以考慮使用解釋器模式产喉。

該模式對(duì)于我們開(kāi)發(fā)人員來(lái)說(shuō),基本上都用不到敢会。除非你想自己開(kāi)發(fā)一種語(yǔ)言曾沈。

解釋器模式真正開(kāi)發(fā)起來(lái)很難,就相當(dāng)于自己開(kāi)發(fā)了一種語(yǔ)言給別人用鸥昏。

解釋器模式UML圖:

應(yīng)用場(chǎng)景

通常來(lái)說(shuō)塞俱,當(dāng)有一個(gè)語(yǔ)言需要解釋執(zhí)行,并且你可將該語(yǔ)言中的句子表示為一個(gè)抽象語(yǔ)法樹(shù)葉吏垮,則可以使用解釋器模式障涯。

EL表達(dá)式的處理

正則表達(dá)式解釋器

SQL語(yǔ)法的解釋器

數(shù)學(xué)表達(dá)式解釋器:Math 、   Expression String Parser 膳汪、 Expression4J

6唯蝶、責(zé)任鏈模式

請(qǐng)求的鏈?zhǔn)教幚怼?zé)任鏈模式

很多情況下,在一個(gè)軟件系統(tǒng)中可以處理某個(gè)請(qǐng)求的對(duì)象不止一個(gè)遗嗽,
例如SCM系統(tǒng)中的采購(gòu)單審批粘我,主任、副董事長(zhǎng)痹换、董事長(zhǎng)和董事會(huì)都可以處理采購(gòu)單征字,他們可以構(gòu)成一條處理采購(gòu)單的鏈?zhǔn)浇Y(jié)構(gòu),
采購(gòu)單沿著這條鏈進(jìn)行傳遞晴音,這條鏈就稱為職責(zé)鏈柔纵。職責(zé)鏈可以是一條直線、一個(gè)環(huán)或者一個(gè)樹(shù)形結(jié)構(gòu)锤躁,最常見(jiàn)的職責(zé)鏈?zhǔn)侵本€型,
即沿著一條單向的鏈來(lái)傳遞請(qǐng)求。鏈上的每一個(gè)對(duì)象都是請(qǐng)求處理者系羞,
職責(zé)鏈模式可以將請(qǐng)求的處理者組織成一條鏈郭计,并讓請(qǐng)求沿著鏈傳遞,
由鏈上的處理者對(duì)請(qǐng)求進(jìn)行相應(yīng)的處理椒振,客戶端無(wú)須關(guān)心請(qǐng)求的處理細(xì)節(jié)以及請(qǐng)求的傳遞昭伸,
只需將請(qǐng)求發(fā)送到鏈上即可,實(shí)現(xiàn)請(qǐng)求發(fā)送者和請(qǐng)求處理者解耦澎迎。

 職責(zé)鏈模式定義如下:

職責(zé)鏈模式(Chain of Responsibility Pattern):避免請(qǐng)求發(fā)送者與接收者耦合在一起庐杨,讓多個(gè)對(duì)象都有可能接收請(qǐng)求,將這些對(duì)象連接成一條鏈夹供,并且沿著這條鏈傳遞請(qǐng)求灵份,直到有對(duì)象處理它為止。職責(zé)鏈模式是一種對(duì)象行為型模式哮洽。

在職責(zé)鏈模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:

  ● Handler(抽象處理者):它定義了一個(gè)處理請(qǐng)求的接口填渠,一般設(shè)計(jì)為抽象類,
                        由于不同的具體處理者處理請(qǐng)求的方式不同鸟辅,因此在其中定義了抽象請(qǐng)求處理方法氛什。
                        因?yàn)槊恳粋€(gè)處理者的下家還是一個(gè)處理者,因此在抽象處理者中定義了一個(gè)抽象處理者類型的對(duì)象
                       (如結(jié)構(gòu)圖中的successor)匪凉,作為其對(duì)下家的引用枪眉。通過(guò)該引用,處理者可以連成一條鏈再层。

  ● ConcreteHandler(具體處理者):它是抽象處理者的子類瑰谜,可以處理用戶請(qǐng)求,在具體處理者類中實(shí)現(xiàn)了抽象
                               處理者中定義的抽象請(qǐng)求處理方法树绩,在處理請(qǐng)求之前需要進(jìn)行判斷萨脑,看是否有相應(yīng)的處理權(quán)限,
                               如果可以處理請(qǐng)求就處理它饺饭,否則將請(qǐng)求轉(zhuǎn)發(fā)給后繼者渤早;
                               在具體處理者中可以訪問(wèn)鏈中下一個(gè)對(duì)象,以便請(qǐng)求的轉(zhuǎn)發(fā)瘫俊。

具體處理者是抽象處理者的子類鹊杖,它具有兩大作用:第一是處理請(qǐng)求,第二是轉(zhuǎn)發(fā)請(qǐng)求扛芽。

責(zé)任鏈模式的優(yōu)缺點(diǎn)

 責(zé)任鏈模式與if…else…相比骂蓖,他的耦合性要低一些,因?yàn)樗褩l件判定都分散到了各個(gè)處理類中川尖,
 并且這些處理類的優(yōu)先處理順序可以隨意設(shè)定登下。責(zé)任鏈模式也有缺點(diǎn),這與if…else…語(yǔ)句的缺點(diǎn)是一樣的,
 那就是在找到正確的處理類之前被芳,所有的判定條件都要被執(zhí)行一遍缰贝,當(dāng)責(zé)任鏈比較長(zhǎng)時(shí),性能問(wèn)題比較嚴(yán)重畔濒。

責(zé)任鏈模式的適用場(chǎng)景

就像開(kāi)始的例子那樣剩晴,假如使用if…else…語(yǔ)句來(lái)組織一個(gè)責(zé)任鏈時(shí)感到力不從心,代碼看上去很糟糕時(shí)侵状,
就可以使用責(zé)任鏈模式來(lái)進(jìn)行重構(gòu)赞弥。

總結(jié)

 責(zé)任鏈模式其實(shí)就是一個(gè)靈活版的if…else…語(yǔ)句,它就是將這些判定條件的語(yǔ)句放到了各個(gè)處理類中趣兄,這樣做的優(yōu)點(diǎn)是比較靈活了绽左,
 但同樣也帶來(lái)了風(fēng)險(xiǎn),比如設(shè)置處理類前后關(guān)系時(shí)诽俯,一定要特別仔細(xì)妇菱,搞對(duì)處理類前后邏輯的條件判斷關(guān)系,
 并且注意不要在鏈中出現(xiàn)循環(huán)引用的問(wèn)題暴区。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闯团,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子仙粱,更是在濱河造成了極大的恐慌房交,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伐割,死亡現(xiàn)場(chǎng)離奇詭異候味,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)隔心,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門白群,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人硬霍,你說(shuō)我怎么就攤上這事帜慢。” “怎么了唯卖?”我有些...
    開(kāi)封第一講書人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵粱玲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我拜轨,道長(zhǎng)抽减,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任橄碾,我火速辦了婚禮卵沉,結(jié)果婚禮上颠锉,老公的妹妹穿的比我還像新娘。我一直安慰自己偎箫,他們只是感情好木柬,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布皆串。 她就那樣靜靜地躺著淹办,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恶复。 梳的紋絲不亂的頭發(fā)上怜森,一...
    開(kāi)封第一講書人閱讀 52,184評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音谤牡,去河邊找鬼副硅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛翅萤,可吹牛的內(nèi)容都是我干的恐疲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼套么,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼培己!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起胚泌,我...
    開(kāi)封第一講書人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤省咨,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后玷室,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體零蓉,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年穷缤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敌蜂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡津肛,死狀恐怖章喉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情快耿,我是刑警寧澤囊陡,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站掀亥,受9級(jí)特大地震影響撞反,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搪花,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一遏片、第九天 我趴在偏房一處隱蔽的房頂上張望嘹害。 院中可真熱鬧,春花似錦吮便、人聲如沸笔呀。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)许师。三九已至,卻和暖如春僚匆,著一層夾襖步出監(jiān)牢的瞬間微渠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工咧擂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逞盆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓松申,卻偏偏與公主長(zhǎng)得像云芦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贸桶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359

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

  • 1 場(chǎng)景問(wèn)題# 1.1 工資表數(shù)據(jù)的整合## 考慮這樣一個(gè)實(shí)際應(yīng)用:整合工資表數(shù)據(jù)舅逸。 這個(gè)項(xiàng)目的背景是這樣的,項(xiàng)目...
    七寸知架構(gòu)閱讀 2,555評(píng)論 0 53
  • 設(shè)計(jì)模式匯總 一刨啸、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用堡赔、多...
    MinoyJet閱讀 3,948評(píng)論 1 15
  • 【學(xué)習(xí)難度:★★★☆☆,使用頻率:★★★★★】直接出處:迭代器模式梳理和學(xué)習(xí):https://github.com...
    BruceOuyang閱讀 1,317評(píng)論 2 1
  • 1 意圖 提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中的各個(gè)元素设联,而又不需暴露該對(duì)象的內(nèi)部表示善已。 2 別名 游標(biāo)(Curse...
    10xjzheng閱讀 537評(píng)論 0 0
  • 不知道有沒(méi)有人相信一夢(mèng)三生! 那是我來(lái)到西安的第一天离例,在學(xué)校煩悶不安的我换团,獨(dú)自一人、不遠(yuǎn)萬(wàn)里去到西安散心宫蛆,那日...
    藏情閱讀 153評(píng)論 0 0