面向?qū)ο笤O(shè)計(jì)的五大原則
單一職責(zé)原則(SRP)
一個(gè)類應(yīng)該僅有一個(gè)職責(zé)。開放封閉原則(OCP)
對(duì)擴(kuò)展開放,對(duì)修改封閉。Liskov 替換原則(LSP)
子類必須能夠替換其基類。這是面向接口編程的基礎(chǔ)。
所有引用基類(父類)的地方必須能透明地使用其子類的對(duì)象。
子類具有擴(kuò)展父類的責(zé)任,而不是重寫的責(zé)任。
在使用里氏代換原則時(shí)需要注意如下幾個(gè)問題:
1.子類的所有方法必須在父類中聲明,或子類必須實(shí)現(xiàn)父類中聲明的所有方法。根據(jù)里氏代換原則,為了保證系統(tǒng)的擴(kuò)展性,在程序中通常使用父類來進(jìn)行定義,如果一個(gè)方法只存在子類中,在父類中不提供相應(yīng)的聲明,則無法在以父類定義的對(duì)象中使用該方法。
2.我們?cè)谶\(yùn)用里氏代換原則時(shí),盡量把父類設(shè)計(jì)為抽象類或者接口,讓子類繼承父類或?qū)崿F(xiàn)父接口,并實(shí)現(xiàn)在父類中聲明的方法,運(yùn)行時(shí),子類實(shí)例替換父類實(shí)例,我們可以很方便地?cái)U(kuò)展系統(tǒng)的功能,同時(shí)無須修改原有子類的代碼,增加新的功能可以通過增加一個(gè)新的子類來實(shí)現(xiàn)。里氏代換原則是開閉原則的具體實(shí)現(xiàn)手段之一。
依賴倒置原則(DIP)
依賴抽象(接口或抽象類),不要依賴具體。接口隔離原則(ISP)
多個(gè)和客戶相關(guān)的接口要好于一個(gè)通用的接口。
設(shè)計(jì)模式的六大原則
開閉原則(Open Close Principle)
開閉原則的意思是:對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。在程序需要進(jìn)行拓展的時(shí)候,不能去修改原有的代碼,實(shí)現(xiàn)一個(gè)熱插拔的效果。簡(jiǎn)言之,是為了使程序的擴(kuò)展性好,易于維護(hù)和升級(jí)。想要達(dá)到這樣的效果,我們需要使用接口和抽象類,后面的具體設(shè)計(jì)中我們會(huì)提到這點(diǎn)。里氏代換原則(Liskov Substitution Principle)
里氏代換原則是面向?qū)ο笤O(shè)計(jì)的基本原則之一。 里氏代換原則中說,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。LSP 是繼承復(fù)用的基石,只有當(dāng)派生類可以替換掉基類,且軟件單位的功能不受到影響時(shí),基類才能真正被復(fù)用,而派生類也能夠在基類的基礎(chǔ)上增加新的行為。里氏代換原則是對(duì)開閉原則的補(bǔ)充。實(shí)現(xiàn)開閉原則的關(guān)鍵步驟就是抽象化,而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。依賴倒轉(zhuǎn)原則(Dependence Inversion Principle)
這個(gè)原則是開閉原則的基礎(chǔ),具體內(nèi)容:針對(duì)對(duì)接口編程,依賴于抽象而不依賴于具體。接口隔離原則(Interface Segregation Principle)
這個(gè)原則的意思是:使用多個(gè)隔離的接口,比使用單個(gè)接口要好。它還有另外一個(gè)意思是:降低類之間的耦合度。由此可見,其實(shí)設(shè)計(jì)模式就是從大型軟件架構(gòu)出發(fā)、便于升級(jí)和維護(hù)的軟件設(shè)計(jì)思想,它強(qiáng)調(diào)降低依賴,降低耦合。迪米特法則,又稱最少知道原則(Demeter Principle)
最少知道原則是指:一個(gè)實(shí)體應(yīng)當(dāng)盡量少地與其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對(duì)獨(dú)立。合成復(fù)用原則(Composite Reuse Principle)
合成復(fù)用原則是指:盡量使用合成/聚合的方式,而不是使用繼承。
創(chuàng)建型模式
1. 簡(jiǎn)單工廠
意圖
在運(yùn)行時(shí)以靈活的方法創(chuàng)建對(duì)象,這些對(duì)象是構(gòu)造方法不能單獨(dú)提供的。
小結(jié)
- 當(dāng)單獨(dú)使用構(gòu)造方法不適于對(duì)象的創(chuàng)建時(shí),那么就使用一個(gè)返回對(duì)象的方法。
- 客戶類和工廠類分開。
- Factory 模式是設(shè)計(jì)模式的委托的一個(gè)例子,因?yàn)槊總€(gè)工廠都是將創(chuàng)建責(zé)任委托給構(gòu)造方法。
- 增加新的需求對(duì)象需修改工廠類。
- 簡(jiǎn)單工廠沒有在 GoF 模式中,經(jīng)常與反射技術(shù)一起用。
2. 工廠模式
是類的創(chuàng)建模式
意圖
定義一個(gè)創(chuàng)建產(chǎn)品對(duì)象的工廠接口,將實(shí)際創(chuàng)建工作推遲到子類。
參與者
- 抽象工廠(Creator)角色: 工廠方法模式的核心, 與應(yīng)用程序無關(guān)。任何在模式中創(chuàng)建的對(duì)象的工廠類必須實(shí)現(xiàn)這個(gè)接口。
- 具體工廠(Concrete Creator)角色: 這個(gè)是實(shí)現(xiàn)抽象工廠接口的具體工廠類, 包含與應(yīng)用程序密切相關(guān)的邏輯, 并且受到應(yīng)用程序調(diào)用以創(chuàng)建產(chǎn)品對(duì)象。
- 抽象產(chǎn)品(Product)角色: 工廠方法模式所創(chuàng)建的對(duì)象的父類或接口。
- 具體產(chǎn)品(Concrete Product)角色: 這個(gè)角色實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠創(chuàng)建。
類圖

小結(jié)
- 使用工廠接口。
- 具體的創(chuàng)建由子類完成,相當(dāng)于簡(jiǎn)單工廠。
- 增加新的需求對(duì)象不需要修改工廠接口。相比簡(jiǎn)單工廠擴(kuò)展性好。
3. 單例模式
意圖
確保一個(gè)類只有一個(gè)確切的實(shí)例,在整個(gè)應(yīng)用程序中都是可訪問的。
小結(jié)
- 當(dāng)一個(gè)類必須有且只有一個(gè)實(shí)例時(shí),使構(gòu)造方法私有化,并且使用共有的存取方法來實(shí)例化一個(gè)靜態(tài)的,私有的變量。
- 盡量減少單態(tài)對(duì)象: 只有在存取方法第一次調(diào)用時(shí)才創(chuàng)建它。Lazy
- 需要單態(tài)對(duì)象的屬性和方法時(shí),不能都定義為靜態(tài) static。
- 單態(tài)能夠擴(kuò)展為一個(gè)類具有兩個(gè)或更多實(shí)例。
- 只有一個(gè)單態(tài)對(duì)象與這個(gè)對(duì)象能在應(yīng)用程序中的任何地方被訪問是同等重要。
4. 抽象工廠模式
設(shè)計(jì)目標(biāo)
提供一個(gè)創(chuàng)建相關(guān)族或者相互依賴對(duì)象的接口,而不指明它們的具體類。別名: Kit
意圖
在軟件系統(tǒng)中,經(jīng)常面臨著“一系列相互依賴的對(duì)象”的創(chuàng)建工作;同時(shí)由于需求的變化,往往存在更多系列對(duì)象的創(chuàng)建工作。
產(chǎn)品等級(jí)結(jié)構(gòu)和產(chǎn)品族
工廠方法針對(duì)一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)
抽象工廠針對(duì)多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)
產(chǎn)品等級(jí)結(jié)構(gòu):產(chǎn)品的繼承結(jié)構(gòu),如一個(gè)抽象類是手機(jī),其子類有蘋果手機(jī)、三星手機(jī)、華為手機(jī),抽象的手機(jī)和具體品牌的手機(jī)構(gòu)成一個(gè)產(chǎn)品結(jié)構(gòu)。
產(chǎn)品族:在抽象工廠模式中,產(chǎn)品族是指同一個(gè)工廠生產(chǎn)的,位于不同產(chǎn)品結(jié)構(gòu)中的一組產(chǎn)品,如蘋果公司的蘋果手機(jī)、蘋果平板電腦、蘋果筆記本。

抽象工廠參與者 Actor
- 抽象工廠(AbstractFactory):聲明生成抽象產(chǎn)品的方法。
- 具體工廠(ConcreteFactory):實(shí)現(xiàn)生成抽象產(chǎn)品的方法,生成一個(gè)具體的產(chǎn)品。
- 抽象產(chǎn)品(AbstractProduct):為一種產(chǎn)品聲明接口。
- 具體產(chǎn)品(Product):定義具體工廠生成具體產(chǎn)品的對(duì)象,實(shí)現(xiàn)抽象產(chǎn)品接口。
- 客戶(Client):我們的應(yīng)用程序,使用抽象產(chǎn)品和抽象工廠生成對(duì)象。
工廠方法是不是潛伏在抽象工廠里面?
抽象工廠:任務(wù)是定義一個(gè)負(fù)責(zé)創(chuàng)建一組產(chǎn)品的接口。
工廠方法:抽象工廠的方法經(jīng)常以工廠方法的方式實(shí)現(xiàn)。
抽象工廠:使用對(duì)象組合。
工廠方法:使用類繼承。
適用性
- 一個(gè)系統(tǒng)要獨(dú)立于他的產(chǎn)品的創(chuàng)建、組合和表示時(shí)。
- 一個(gè)系統(tǒng)要有多個(gè)產(chǎn)品系列中的一個(gè)來配置時(shí)。
- 當(dāng)你要強(qiáng)調(diào)一系列相關(guān)的產(chǎn)品對(duì)象的設(shè)計(jì)以便進(jìn)行聯(lián)合使用時(shí)。
- 當(dāng)你提供一個(gè)產(chǎn)品類庫(kù),而只是想顯示它們的接口而不是實(shí)現(xiàn)時(shí)。
優(yōu)缺點(diǎn)
- 它分離了具體的類
- 它使得易于交換產(chǎn)品系列
- 它有利于產(chǎn)品的一致性
- 難以支持新種類的產(chǎn)品
5. 建造者模式
意圖
將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
復(fù)雜對(duì)象:由很多其他的對(duì)象(part)組合而成。
結(jié)構(gòu)圖

Builder模式中的角色:
- Builder
- ConcreteBuilder(具體工廠)
- Product(產(chǎn)品)
- Part(部件)
- Director(導(dǎo)向器)
效果
- 它使你可以改變一個(gè)產(chǎn)品的內(nèi)部表示。
- 它將構(gòu)造代碼和表示代碼分開。
- 它使你可對(duì)構(gòu)造過程更精細(xì)的控制。
結(jié)構(gòu)型模式
討論的是類和對(duì)象的結(jié)構(gòu),它采用繼承機(jī)制來組合接口或?qū)崿F(xiàn)(類結(jié)構(gòu)型模式),或者通過聚合或依賴對(duì)象,從而實(shí)現(xiàn)新的功能(對(duì)象結(jié)構(gòu)型模式)。
1. 適配器模式
意圖
將一個(gè)類的接口轉(zhuǎn)化成客戶希望的另外一個(gè)接口。Adapter模式使得原來由于接口不兼容而不能使其工作的那些類可以一起工作。
別名:包裝器 Wrapper
結(jié)構(gòu)圖
類適配器

對(duì)象適配器

適用性
- 你想使用一個(gè)已經(jīng)存在的類,而它的接口不符合你的需要。
- 你想創(chuàng)建一個(gè)可以復(fù)用的類,該類可以與其他不相關(guān)的類或不可預(yù)見的類協(xié)同工作。
- 你想使用一些已經(jīng)存在的子類,但是不可能對(duì)每一個(gè)都進(jìn)行子類化以匹配它們的接口對(duì)象適配器可以適配他的父類接口。
兩種適配器效果
類適配器
- 用一個(gè)具體的 Adapter 類對(duì) Adaptee 和 Target 進(jìn)行匹配。(結(jié)果是當(dāng)我們想要匹配一個(gè)類以及所有的子類時(shí),類 Adapter 將不能勝任工作)
- 使用 Adapter 可以重定義 Adaptee 的部分行為,因?yàn)?Adapter 是 Adaptee 的一個(gè)子類。Overriding
- 僅僅引入了一個(gè)對(duì)象,并不需要額外的指針間接得到 Adaptee。
對(duì)象適配器
- 允許一個(gè)Adapter與多個(gè)Adaptee同時(shí)工作。
- 使得重定義Adaptee的行為比較困難。
2. 橋接模式
意圖
將抽象部分與實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。(抽象類)
abstract class XXX 與 interface XXX 的區(qū)別
- is a(extends) ----- like a(implements)
- 可以有具體行為 ----- 不允許
- 可以帶屬性 ----- final 常量
動(dòng)機(jī)
當(dāng)一個(gè)抽象可能有多個(gè)實(shí)現(xiàn)時(shí),通常用繼承來協(xié)調(diào)它們。抽象類定義
對(duì)該抽象的接口,而具體的子類則用不同的方式加以實(shí)現(xiàn)。但是此方
法有時(shí)不夠靈活。繼承機(jī)制將抽象部分與它的實(shí)現(xiàn)部分固定在一起,
使得難以對(duì)抽象部分和實(shí)現(xiàn)部分獨(dú)立地進(jìn)行修改、擴(kuò)充和重用。
繼承機(jī)制的不足
- 擴(kuò)展 Window 抽象使之適用于不同的種類的窗口或新的系統(tǒng)平臺(tái)很不方便
- 繼承機(jī)制使得客戶代碼與平臺(tái)相關(guān)
結(jié)構(gòu)圖

適用性
- 你不希望在抽象和他的實(shí)現(xiàn)部分之間有一個(gè)固定的綁定關(guān)系。
- 類的抽象以及它的實(shí)現(xiàn)都應(yīng)該通過生成子類的方法加以擴(kuò)充。通過 Bridge 模式使你可以對(duì)不同的抽象接口和實(shí)現(xiàn)進(jìn)行組合,并分別對(duì)它們進(jìn)行擴(kuò)充。
- 對(duì)一個(gè)抽象的實(shí)現(xiàn)部分的修改應(yīng)對(duì)客戶不產(chǎn)生影響,客戶端代碼不必重新編譯。
- 雖然在系統(tǒng)中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨(dú)立變化,設(shè)計(jì)要求需要獨(dú)立管理這兩者。
3. 組合模式
意圖
將對(duì)象組合成樹型表示“部分—整體”的層次結(jié)構(gòu)。Composite 使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。(具有共同接口)
適用性
- 你想表示的對(duì)象的部分—整體層次結(jié)構(gòu)。
- 你希望用戶忽略組合對(duì)象與單個(gè)對(duì)象的不同,用戶將統(tǒng)一地使用組合結(jié)構(gòu)中的所有對(duì)象。
結(jié)構(gòu)圖

效果
- 定義了包含基本對(duì)象和組合對(duì)象的類層次結(jié)構(gòu)。客戶代碼中,任何用到基本對(duì)象的地方都可以使用組合對(duì)象。
- 簡(jiǎn)化客戶代碼,客戶可以一致地使用組合結(jié)構(gòu)和單個(gè)對(duì)象。
- 使得更容易增加新類型的組件,新定義的 CompositeComponent 或 LeafComponent 自動(dòng)地與已有的結(jié)構(gòu)和客戶代碼一起工作。
- 使你的設(shè)計(jì)變得更加一般化,也會(huì)產(chǎn)生一些問題,那就是很難限制組合中的組件。
缺點(diǎn)
- 控制Component類型不太容易
- 增加新的行為很困難//Decorator
4. 裝飾者模式
意圖
動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來說,Decorator模式相比生成子類(繼承)更為靈活。
裝飾模式滿足開放-封閉原則!
適用性
- 在不影響其他對(duì)象的情況下,給單個(gè)對(duì)象添加職責(zé)。
- 處理那些可以撤銷的職責(zé),簡(jiǎn)化原有的類。
- 當(dāng)不能采用生成子類的方法進(jìn)行擴(kuò)充時(shí)。
結(jié)構(gòu)圖

效果
- 比靜態(tài)繼承更加靈活。
- 避免在層次結(jié)構(gòu)高層的類有太多的特征。
- 有許多小對(duì)象(裝飾類)。
- 一個(gè)被裝飾了的組件和原來組件是有差別的。
5. 外觀模式
意圖
為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,F(xiàn)a?ade 模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。解耦!
結(jié)構(gòu)圖

適用性
- 當(dāng)你要為一個(gè)復(fù)雜子系統(tǒng)提供一個(gè)簡(jiǎn)單接口時(shí)。(往往是具體類)
- 客戶程序與抽象類的實(shí)現(xiàn)部分之間存在著很大的依賴性。引入 Fa?ade 將這個(gè)子系統(tǒng)與客戶以及其他的子系統(tǒng)分離,可以提高子系統(tǒng)的獨(dú)立性和可移植性。
- 如果子系統(tǒng)之間是相互依賴的,你可以讓它們僅通過Fa?ade進(jìn)行通訊,從而簡(jiǎn)化了它們之間的依賴關(guān)系。
- 子系統(tǒng)中任何類對(duì)其方法進(jìn)行修改,不影響外觀類的代碼。
效果
- 它對(duì)客戶屏蔽子系統(tǒng)組建,因而減少了客戶處理的對(duì)象的數(shù)目并使得子系統(tǒng)使用起來更加方便。
- 它實(shí)現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系,而子系統(tǒng)內(nèi)部的功能組建往往是緊耦合的。松耦合關(guān)系使得子系統(tǒng)的組建變化不會(huì)影響到它的客戶。// 高內(nèi)聚,低耦合。
- 如果應(yīng)用需要,它并不限制客戶使用子系統(tǒng)。因此你可以在系統(tǒng)易用性和通用性之間加以選擇。也可以創(chuàng)建不同需求的外觀類。
6. 代理模式
意圖
為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。
別名:Surrogate/Broker
結(jié)構(gòu)圖

種類
- 遠(yuǎn)程(Remote)代理:為一個(gè)位于不同地址空間的對(duì)象提供一個(gè)局域代表對(duì)象。本地
- 虛擬(Virtual)代理:根據(jù)需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對(duì)象,使得此對(duì)象只在需要時(shí)才會(huì)被真正創(chuàng)建。
7. 享元模式
行為型模式
- 行為模式涉及到算法和對(duì)象間職責(zé)的分配。
- 行為模式不僅描述類和對(duì)象的模式,還描述它們之間的通信模式。
- 使用繼承機(jī)制在類間分派行為
- 使用對(duì)象聚合或依賴
- 行為型模式涉及怎樣合理地設(shè)計(jì)對(duì)象之間的交互通信,以及怎樣合理為對(duì)象分配職責(zé),讓設(shè)計(jì)富有彈性,易維護(hù),易復(fù)用。
1. 迭代器模式
意圖
提供一種方法順序訪問一個(gè)聚合對(duì)象中的各個(gè)元素,而又不暴露該對(duì)象的內(nèi)部表示。
別名: 游標(biāo)(Cursor)
適用性
- 訪問一個(gè)聚合對(duì)象的內(nèi)容而無需暴露它的內(nèi)部表示。
- 支持聚合對(duì)象的多種遍歷。
- 為遍歷不同的聚合結(jié)構(gòu)提供統(tǒng)一的接口。
結(jié)構(gòu)圖

效果(作用)
- 它支持以不同的方式遍歷一個(gè)聚合,復(fù)雜的聚合可以多種方式遍歷。例如,代碼生成和語義檢查要遍歷語法分析樹。中序或前序(看圖示) next() previous()
- 迭代器簡(jiǎn)化了聚合的接口,有了迭代器的遍歷接口,聚合本身就不需要類似的遍歷接口。
- 在同一個(gè)聚合上可以有多個(gè)遍歷,每個(gè)迭代器保持它自己的遍歷狀態(tài)。
2. 模板模式
意圖
定義一個(gè)操作中的算法骨架,而將一些步驟延遲到子類中。TemplateMethod 使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
Template 設(shè)計(jì)模式的目標(biāo)是處理算法的多變性。
結(jié)構(gòu)圖


適用性
- 一次性實(shí)現(xiàn)一個(gè)算法的不變的部分,并將可變的行為留給子類來實(shí)現(xiàn)。
- 各子類中的公共地行為應(yīng)被提取出來并集中到父類中避免代碼重復(fù)。
實(shí)現(xiàn)要點(diǎn)
- TemplateMethod 模式是一種非?;A(chǔ)性的設(shè)計(jì)模式,在面向?qū)ο笾杏兄罅康膽?yīng)用。為很多應(yīng)用程序框架提供了靈活的擴(kuò)展點(diǎn),是代碼復(fù)用方面的基本實(shí)現(xiàn)結(jié)構(gòu)。Spring 框架 IOC
- 除了可以靈活應(yīng)對(duì)子步驟地變化外,“Don’t call me, Let me call you”的反向控制結(jié)構(gòu)是TemplateMethod的典型應(yīng)用。 Inverse of Control
- 在具體實(shí)現(xiàn)方面,被 TemplateMethod 調(diào)用的虛方法可以具體實(shí)現(xiàn),也可以空實(shí)現(xiàn),空實(shí)現(xiàn)的方法或默認(rèn)的實(shí)現(xiàn)叫“hook operation”鉤子操作。
- 盡量減少 primitive operation,需要重新定義的操作越多,子類程序越復(fù)雜。
3. 觀察者模式
意圖
定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。
別名:發(fā)布-訂閱(Publish-Subscribe)
適用性
- 當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一方面。將這二者封裝在獨(dú)立的對(duì)象中以使它們可以各自獨(dú)立地改變和復(fù)用。
- 當(dāng)對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象,而不知道具體有多少對(duì)象有待改變。
- 當(dāng)一個(gè)對(duì)象必須通知其他對(duì)象,你不希望這些對(duì)象是緊密耦合的。
結(jié)構(gòu)圖

4. 責(zé)任鏈模式
意圖
使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接受收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。
該模式構(gòu)造一系列分別擔(dān)當(dāng)不同的職責(zé)的類的對(duì)象來共同完成一個(gè)任務(wù),
這些類的對(duì)象之間像鏈條一樣緊密相連,所以被稱作職責(zé)鏈模式。
實(shí)現(xiàn)要點(diǎn)
- 對(duì)象鏈的組織:需要將某任務(wù)的所有職責(zé)執(zhí)行對(duì)象以鏈Chain的形式加以組織。
- 消息或請(qǐng)求的傳遞:將消息或請(qǐng)求沿著對(duì)象鏈傳遞,以讓處于對(duì)象鏈中的對(duì)象得到處理機(jī)會(huì)。
- 處于對(duì)象鏈中的對(duì)象的職責(zé)分配:不同的對(duì)象完成不同的職責(zé)。
- 任務(wù)的完成:處于對(duì)象鏈的末尾的對(duì)象結(jié)束任務(wù)并停止消息或請(qǐng)求的繼續(xù)傳遞。
適用性
- 有多個(gè)對(duì)象可以處理一個(gè)請(qǐng)求,哪個(gè)對(duì)象處理該請(qǐng)求運(yùn)行時(shí)刻確定。
- 你想在不明確指定接收者的情況下,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求。
- 可處理一個(gè)請(qǐng)求的對(duì)象集合應(yīng)被動(dòng)態(tài)指定。(改變鏈內(nèi)的成員或它們的次序)
結(jié)構(gòu)圖

效果
- 降低耦合。該模式使得一個(gè)對(duì)象無需知道是其它哪一個(gè)對(duì)象處理其請(qǐng)求。對(duì)象僅需知道該請(qǐng)求會(huì)被處理。
- 增強(qiáng)了給對(duì)象指派職責(zé) Responsibility 的靈活性。在運(yùn)行時(shí)刻對(duì)該鏈進(jìn)行動(dòng)態(tài)的增加或修改處理一個(gè)請(qǐng)求的那些職責(zé)
- 職責(zé)的分擔(dān)。每個(gè)類只需要處理自己該處理的工作(不該處理的傳遞給下一個(gè)對(duì)象完成),明確各類的責(zé)任范圍,符合類的最小封裝原則。SRP
- 請(qǐng)求不保證被接受。一個(gè)請(qǐng)求可能因該鏈沒有被正確配置而得不到處理。
5. 中介模式
意圖
用一個(gè)中介對(duì)象來封裝一系列對(duì)象交互。中介者使各對(duì)象不需要相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。
迪米特法則
迪米特法則(Law of Demeter)又叫作最少知識(shí)原則(Least Knowledge Principle 簡(jiǎn)寫LKP),就是說一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象有盡可能少的了解。
迪米特法則不希望類之間建立直接的聯(lián)系。
迪米特法則應(yīng)用:外觀模式 facade 和中介者模式 mediator
迪米特法則中,對(duì)于一個(gè)對(duì)象,其朋友包括以下幾類:
- 當(dāng)前對(duì)象本身;
- 以參數(shù)形式傳入到當(dāng)前對(duì)象方法中的對(duì)象;
- 當(dāng)前對(duì)象的成員對(duì)象;
- 如果當(dāng)前對(duì)象的成員對(duì)象是一個(gè)集合,那么集合中的元素也都是朋友;
- 當(dāng)前對(duì)象所創(chuàng)建的對(duì)象。
結(jié)構(gòu)圖

和外觀模式的區(qū)別
-
中介者模式解決的是多個(gè)對(duì)象之間的通信問題,減少類之間的關(guān)聯(lián)。
外觀模式解決的是子系統(tǒng)的接口復(fù)雜度問題。 -
中介者模式中對(duì)象可以向中介者請(qǐng)求。
外觀模式中對(duì)象不會(huì)對(duì)外觀有任何協(xié)作請(qǐng)求。
特點(diǎn)
- 減少子類的生成。Mediator 將原本分布于多個(gè)對(duì)象間的行為集中在一起。改變這些行為只需生成 Mediator 的子類即可。
- 將各 Colleague 解耦。Mediator 有利于各 Colleague 類間的松耦合。你可以獨(dú)立的改變和復(fù)用各 Colleague 類和 Mediator 類。
- 簡(jiǎn)化了對(duì)象協(xié)議。用 Mediator 和各 Colleague 間的一對(duì)多的交互來替代多對(duì)多的交互。一對(duì)多的關(guān)系更易于理解、維護(hù)和擴(kuò)展。
- 使控制集中化。中介者模式將交互的復(fù)雜性變?yōu)橹薪檎叩膹?fù)雜性。中介者封裝了協(xié)議,它可能比任何一個(gè) Colleague 都復(fù)雜。
6. 狀態(tài)模式
意圖
允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來似乎修改了它的類。
為什么說 Thermometer 類的實(shí)例在應(yīng)對(duì)需求變化時(shí)缺乏彈性?
因?yàn)?showMessage( ) 的行為依賴于 temperature 大小
重新設(shè)計(jì)Thermometer類:將對(duì)象的狀態(tài)從當(dāng)前的對(duì)象中分離出去,即將一個(gè)對(duì)象的狀態(tài)封裝在另外一個(gè)類中。
結(jié)構(gòu)圖

優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 使用類封裝對(duì)象的一種狀態(tài),容易擴(kuò)增新的狀態(tài)。
- 在 Context 中不必出現(xiàn)大量的條件判斷語句。
- 用戶很方便地切換 Context 實(shí)例的狀態(tài)。狀態(tài)切換
- Context 的各個(gè)對(duì)象可以共享一個(gè)狀態(tài)對(duì)象。
缺點(diǎn):
- 較多的 ConcreteState 子類。
適用性
- 對(duì)象的行為依賴于它的狀態(tài),并且它必須在運(yùn)行時(shí)根據(jù)狀態(tài)改變它的行為。
- 需要編寫大量的條件語句來決定一個(gè)操作的行為,而且這些條件恰好表示對(duì)象的一種狀態(tài)。