設計模式精簡圖冊

渡口一艘船發表於2019-02-19

設計模式精簡圖冊

首發於我的公眾號

設計模式圖冊

設計模式分類

建立型模式:

主要用於建立物件,包括

  • 工廠方法(Factory Method)
  • 抽象工廠(Abstract Factory)
  • 單例(Singleton)
  • 生成器(Builder)
  • 原型(Prototype)

結構型模式:

用於處理類或者物件的組合,包括

  • 介面卡(Adapter)
  • 裝飾者(Decorator)
  • 代理(Proxy)
  • 外觀(Facade)
  • 橋接(Bridge Pattern)
  • 組合(Composite)
  • 輕量(Flyweigh)

行為型模式:

用於描述類與物件怎樣的互動和分配職責,包括

  • 策略(Strategy)
  • 觀察者(Observer)
  • 命令(Command)
  • 模板方法(Template Method)
  • 迭代器(Iterator)
  • 狀態(State)
  • 責任鏈(Chain)
  • 直譯器(Interpreter)
  • 中介者(Mediator)
  • 備忘錄(Memo)
  • 訪問者(Visitor)

設計原則

單一職責原則(Single responsibility principle)

  • 核心 不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。
  • 問題產生 類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時,有可能會導致原本執行正常的職責P2功能發生故障。
  • 解決方案 遵循單一職責原則。分別建立兩個類T1、T2,使T1完成職責P1功能,T2完成職責P2功能。這樣,當修改類T1時,不會使職責P2發生故障風險;同理,當修改T2時,也不會使職責P1發生故障風險。

但是由於職責擴散會導致在實際中往往會有悖於單一職責

里氏代換原則(Liskov Substitution Principle LSP)

  • 核心 所有引用基類的地方必須能透明地使用其子類的物件。
  • 問題產生 有一功能P1,由類A完成。現需要將功能P1進行擴充套件,擴充套件後的功能為P,其中P由原有功能P1與新功能P2組成。新功能P由類A的子類B來完成,則子類B在完成新功能P2的同時,有可能會導致原有功能P1發生故障。
  • 解決方案 當使用繼承時,遵循里氏替換原則。類B繼承類A時,除新增新的方法完成新增功能P2外,儘量不要重寫父類A的方法,也儘量不要過載父類A的方法。

繼承包含這樣一層含義:父類中凡是已經實現好的方法(相對於抽象方法而言),實際上是在設定一系列的規範和契約,雖然它不強制要求所有的子類必須遵從這些契約,但是如果子類對這些非抽象方法任意修改,就會對整個繼承體系造成破壞。而里氏替換原則就是表達了這一層含義。

繼承作為物件導向三大特性之一,在給程式設計帶來巨大便利的同時,也帶來了弊端。比如使用繼承會給程式帶來侵入性,程式的可移植性降低,增加了物件間的耦合性,如果一個類被其他的類所繼承,則當這個類需要修改時,必須考慮到所有的子類,並且父類修改後,所有涉及到子類的功能都有可能會產生故障。

介面隔離原則(Interface Segregation Principle)

  • 核心 不應該依賴它不需要的介面;一個類對另一個類的依賴應該建立在最小的介面上
  • 問題產生 類A通過介面I依賴類B,類C通過介面I依賴類D,如果介面I對於類A和類B來說不是最小介面,則類B和類D必須去實現他們不需要的方法。
  • 解決方案 將臃腫的介面I拆分為獨立的幾個介面,類A和類C分別與他們需要的介面建立依賴關係。也就是採用介面隔離原則。

介面隔離原則跟之前的單一職責原則很相似,其實不然。其一,單一職責原則原注重的是職責;而介面隔離原則注重對介面依賴的隔離。其二,單一職責原則主要是約束類,其次才是介面和方法,它針對的是程式中的實現和細節;而介面隔離原則主要約束介面介面,主要針對抽象,針對程式整體框架的構建。

採用介面隔離原則對介面進行約束時,要注意以下幾點:

  • 介面儘量小,但是要有限度。對介面進行細化可以提高程式設計靈活性是不掙的事實,但是如果過小,則會造成介面數量過多,使設計複雜化。所以一定要適度。
  • 為依賴介面的類定製服務,只暴露給呼叫的類它需要的方法,它不需要的方法則隱藏起來。只有專注地為一個模組提供定製服務,才能建立最小的依賴關係。
  • 提高內聚,減少對外互動。使介面用最少的方法去完成最多的事情。

運用介面隔離原則,一定要適度,介面設計的過大或過小都不好。設計介面的時候,只有多花些時間去思考和籌劃,才能準確地實踐這一原則。

迪米特原則(Law of Demeter/Least Knowledge Principle )

  • 核心 迪米特法則又叫最少知道原則,一個物件應該對其他物件保持最少的瞭解。
  • 問題產生 類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。
  • 解決方案 儘量降低類與類之間的耦合。

通俗的來講,就是一個類對自己依賴的類知道的越少越好。也就是說,對於被依賴的類來說,無論邏輯多麼複雜,都儘量地的將邏輯封裝在類的內部,對外除了提供的public方法,不對外洩漏任何資訊, 迪米特法則還有一個更簡單的定義:只與直接的朋友通訊。首先來解釋一下什麼是直接的朋友:每個物件都會與其他物件有耦合關係,只要兩個物件之間有耦合關係,我們就說這兩個物件之間是朋友關係。耦合的方式很多,依賴、關聯、組合、聚合等。其中,我們稱出現成員變數、方法引數、方法返回值中的類為直接的朋友,而出現在區域性變數中的類則不是直接的朋友。也就是說,陌生的類最好不要作為區域性變數的形式出現在類的內部。

依賴倒置原則(Dependence Inversion Principle)

  • 核心 高層模組不應該依賴低層模組,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。
  • 問題產生 類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的程式碼來達成。這種場景下,類A一般是高層模組,負責複雜的業務邏輯;類B和類C是低層模組,負責基本的原子操作;假如修改類A,會給程式帶來不必要的風險。
  • 解決方案 將類A修改為依賴介面I,類B和類C各自實現介面I,類A通過介面I間接與類B或者類C發生聯絡,則會大大降低修改類A的機率。

依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象為基礎搭建起來的架構比以細節為基礎搭建起來的架構要穩定的多。在java中,抽象指的是介面或者抽象類,細節就是具體的實現類,使用介面或者抽象類的目的是制定好規範和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。

依賴倒置原則的核心思想是面向介面程式設計,

開閉原則(Open Close Principle)

  • 核心 一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。
  • 問題產生 在軟體的生命週期內,因為變化、升級和維護等原因需要對軟體原有程式碼進行修改時,可能會給舊程式碼中引入錯誤,也可能會使我們不得不對整個功能進行重構,並且需要原有程式碼經過重新測試。
  • 解決方案 當軟體需要變化時,儘量通過擴充套件軟體實體的行為來實現變化,而不是通過修改已有的程式碼來實現變化。

開閉原則無非就是想表達這樣一層意思:用抽象構建框架,用實現擴充套件細節。因為抽象靈活性好,適應性廣,只要抽象的合理,可以基本保持軟體架構的穩定。而軟體中易變的細節,我們用從抽象派生的實現類來進行擴充套件,當軟體需要發生變化時,我們只需要根據需求重新派生一個實現類來擴充套件就可以了。當然前提是我們的抽象要合理,要對需求的變更有前瞻性和預見性才行。

幾個原則的關聯性

用抽象構建框架,用實現擴充套件細節的注意事項而已:

  • 單一職責原則告訴我們實現類要職責單一;
  • 里氏替換原則告訴我們不要破壞繼承體系;
  • 依賴倒置原則告訴我們要面向介面程式設計;
  • 介面隔離原則告訴我們在設計介面的時候要精簡單一;
  • 迪米特法則告訴我們要降低耦合。 而開閉原則是總綱,他告訴我們要對擴充套件開放,對修改關閉。

建立型設計模式(建立物件)

工廠方法(Factory Method Pattern)

名稱
Factory Method
結構
設計模式精簡圖冊
動機
定義一個用於建立物件的介面,讓子類決定例項化哪一個類。Factory Method 使一個類的例項化延遲到其子類。
適用性
  • 當一個類不知道它所必須建立的物件的類的時候。
  • 當一個類希望由它的子類來指定它所建立的物件的時候。
  • 當類將建立物件的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一資訊區域性化的時候。
優點
  • 在工廠方法中,使用者只需要知道所要產品的具體工廠,無須關係具體的建立過程,甚至不需要具體產品類的類名。
  • 在系統增加新的產品時,我們只需要新增一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了“開閉原則”。
缺點
  • 每次增加一個產品時,都需要增加一個具體類和物件實現工廠,是的系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。
小結
  • 簡單工廠模式的要點就在於當你需要什麼,只需要傳入一個正確的引數,就可以獲取你所需要的物件,而無須知道其建立細節。
  • 簡單工廠模式最大的優點在於實現物件的建立和物件的使用分離,但是如果產品過多時,會導致工廠程式碼非常複雜。

抽象工廠(Abstract Factory Pattern)

名稱
Abstract Factory
結構
設計模式精簡圖冊
動機
提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。
適用性
  • 一個系統要獨立於它的產品的建立、組合和表示時。
  • 一個系統要由多個產品系列中的一個來配置時。
  • 當你要強調一系列相關的產品物件的設計以便進行聯合使用時。
  • 當你提供一個產品類庫,而只想顯示它們的介面而不是實現時。
優點
  • 抽象工廠隔離了具體類的生成,是的客戶端不需要知道什麼被建立。所有的具體工廠都實現了抽象工廠中定義的公共介面,因此只需要改變具體工廠的例項,就可以在某種程度上改變整個軟體系統的行為。
  • 當一個產品族中的多個物件被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的物件。
缺點
  • 新增新的行為時比較麻煩。如果需要新增一個新產品族物件時,需要更改介面及其下所有子類,這必然會帶來很大的麻煩。
小結
  • 抽象工廠模式中主要的優點在於具體類的隔離,是的客戶端不需要知道什麼被建立了。其缺點在於增加新的等級產品結構比較複雜,需要修改介面及其所有子類。

生成器/建造者模式(Builder Pattern)

名稱
Builder
結構
設計模式精簡圖冊
動機
將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
適用性
  • 當建立複雜物件的演算法應該獨立於該物件的組成部分以及它們的裝配方式時。
  • 當構造過程必須允許被構造的物件有不同的表示時。
優點
  • 將複雜產品的建立步驟分解在不同的方法中,使得建立過程更加清晰,使得我們能夠更加精確的控制複雜物件的產生過程。
  • 將產品的建立過程與產品本身分離開來,可以使用相同的建立過程來得到不同的產品。也就說細節依賴抽象。
  • 每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便地替換具體建造者或增加新的具體建造者,使用者使用不同的具體建造者即可得到不同的產品物件。
缺點
  • 建造者模式所建立的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制。
  • 如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。
小結
  • 建造者模式是將一個複雜物件的建立過程給封裝起來,客戶只需要知道可以利用物件名或者型別就能夠得到一個完整的物件例項,而不需要關心物件的具體建立過程。
  • 建造者模式將物件的建立過程與物件本身隔離開了,使得細節依賴於抽象,符合依賴倒置原則。可以使用相同的建立過程來建立不同的產品物件。

原型模式(Prototype Pattern)

名稱
Prototype
結構
設計模式精簡圖冊
動機
用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
適用性
  • 當要例項化的類是在執行時刻指定時,例如,通過動態裝載;或者
  • 為了避免建立一個與產品類層次平行的工廠類層次時;或者
  • 當一個類的例項只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工例項化該類更方便一些。
優點
  • 如果建立新的物件比較複雜時,可以利用原型模式簡化物件的建立過程,同時也能夠提高效率。
  • 可以使用深克隆保持物件的狀態。
  • 原型模式提供了簡化的建立結構。
缺點
  • 在實現深克隆的時候可能需要比較複雜的程式碼。
  • 需要為每一個類配備一個克隆方法,而且這個克隆方法需要對類的功能進行通盤考慮,這對全新的類來說不是很難,但對已有的類進行改造時,不一定是件容易的事,必須修改其原始碼,違背了“開閉原則”。
小結
  • 原型模式向客戶隱藏了建立物件的複雜性。客戶只需要知道要建立物件的型別,然後通過請求就可以獲得和該物件一模一樣的新物件,無須知道具體的建立過程。
  • 克隆分為淺克隆和深克隆兩種。
  • 我們雖然可以利用原型模式來獲得一個新物件,但有時物件的複製可能會相當的複雜,比如深克隆。

單例模式(Singleton Pattern)

名稱
Singleton
結構
設計模式精簡圖冊
動機
保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。
適用性
  • 當類只能有一個例項而且客戶可以從一個眾所周知的訪問點訪問它時。
  • 當這個唯一例項應該是通過子類化可擴充套件的,並且客戶應該無需更改程式碼就能使用一個擴充套件的例項時。
優點
  • 節約了系統資源。由於系統中只存在一個例項物件,對與一些需要頻繁建立和銷燬物件的系統而言,單 例模式無疑節約了系統資源和提高了系統的效能。
  • 因為單例類封裝了它的唯一例項,所以它可以嚴格控制客戶怎樣以及何時訪問它。
缺點
  • 由於單例模式中沒有抽象層,因此單例類的擴充套件有很大的困難。
  • 單例類的職責過重,在一定程度上違背了“單一職責原則”。
小結
  • 單例模式中確保程式中一個類最多隻有一個例項。
  • 單例模式的構造器是私有了,而且它必須要提供例項的全域性訪問點。
  • 單例模式可能會因為多執行緒的問題而帶來安全隱患。
public class BetterSingleton {

    private BetterSingleton2() {
    }

    public static BetterSingleton getInstance() {
        return Singleton.BETTER_SINGLETON;
    }

    publicstatic class Singleton{
      private static final  BetterSingleton BETTER_SINGLETON = new BetterSingleton();
    }
}
複製程式碼

建立型設計模式小結

模式 場景發散 一句話概括
工廠方法(Factory Method) new太多如何管理 生產系列產品。
抽象工廠(Abstract Factory) new太多如何管理 一次生產多個不同產品。
生成器(Builder) 車手選車 生產有很多元件的產品。
原型(Prototype) 複製不能很難 克隆物件。
單件(Singleton) 如何管理全域性資訊 全域性只有一個。

結構型設計模式(處理類或者物件的組合)

橋接模式(Bridge Pattern)

名稱
Bridge
結構
設計模式精簡圖冊
動機
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
適用性
  • 如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承聯絡,通過橋接模式可以使它們在抽象層建立一個關聯關係。
  • 對於那些不希望使用繼承或因為多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤為適用
  • 一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴充套件。
優點
  • 分離抽象介面及其實現部分。提高了比繼承更好的解決方案。
  • 橋接模式提高了系統的可擴充性,在兩個變化維度中任意擴充套件一個維度,都不需要修改原有系統。
  • 實現細節對客戶透明,可以對使用者隱藏實現細節。
缺點
  • 橋接模式的引入會增加系統的理解與設計難度,由於聚合關聯關係建立在抽象層,要求開發者針對抽象進行設計與程式設計。
  • 橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用範圍具有一定的侷限性。
小結
  • 橋接模式實現了抽象化與實現化的脫耦。他們兩個互相獨立,不會影響到對方。
  • 對於兩個獨立變化的維度,使用橋接模式再適合不過了。
  • 對於“具體的抽象類”所做的改變,是不會影響到客戶。

輕量模式/享元模式(FlyWeightPattern)

名稱
Flyweight
結構
設計模式精簡圖冊
動機
運用共享技術有效地支援大量細粒度的物件。
適用性
  • 一個應用程式使用了大量的物件。
  • 完全由於使用大量的物件,造成很大的儲存開銷。
  • 物件的大多數狀態都可變為外部狀態。
  • 如果刪除物件的外部狀態,那麼可以用相對較少的共享物件取代很多組物件。
  • 應用程式不依賴於物件標識。由於F l y w e i g h t 物件可以被共享,對於概念上明顯有別的物件,標識測試將返回真值。
優點
  • 享元模式的優點在於它能夠極大的減少系統中物件的個數。
  • 享元模式由於使用了外部狀態,外部狀態相對獨立,不會影響到內部狀態,所以享元模式使得享元物件能夠在不同的環境被共享。
缺點
  • 由於享元模式需要區分外部狀態和內部狀態,使得應用程式在某種程度上來說更加複雜化了。
  • 為了使物件可以共享,享元模式需要將享元物件的狀態外部化,而讀取外部狀態使得執行時間變長。
小結
  • 享元模式可以極大地減少系統中物件的數量。但是它可能會引起系統的邏輯更加複雜化。
  • 享元模式的核心在於享元工廠,它主要用來確保合理地共享享元物件。
  • 內部狀態為不變共享部分,儲存於享元享元物件內部,而外部狀態是可變部分,它應當由客戶端來負責。

外觀模式(Facade Pattern)

名稱
Facade
結構
設計模式精簡圖冊
動機
為子系統中的一組介面提供一個一致的介面,F a c a d e 模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
適用性
  • 當你要為一個複雜子系統提供一個簡單介面時。子系統往往因為不斷演化而變得越來越複雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的使用者帶來一些使用上的困難。F a c a d e 可以提供一個簡單的預設檢視,這一檢視對大多數使用者來說已經足夠,而那些需要更多的可定製性的使用者可以越過f a c a d e 層。
  • 客戶程式與抽象類的實現部分之間存在著很大的依賴性。引入f a c a d e 將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
  • 當你需要構建一個層次結構的子系統時,使用f a c a d e 模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過f a c a d e 進行通訊,從而簡化了它們之間的依賴關係。
優點
  • 引入外觀模式,是客戶對子系統的使用變得簡單了,減少了與子系統的關聯物件,實現了子系統與客戶之間的鬆耦合關係。
  • 只是提供了一個訪問子系統的統一入口,並不影響使用者直接使用子系統類
  • 降低了大型軟體系統中的編譯依賴性,並簡化了系統在不同平臺之間的移植過程
缺點
  • 不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性
  • 在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的原始碼,違背了“開閉原則”
小結
  • 外觀模式的主要優點就在於減少了客戶與子系統之間的關聯物件,使用客戶對子系統的使用變得簡單了,也實現了客戶端與子系統之間的鬆耦合關係。它的缺點就在於違背了“開閉原則”。
  • 如果需要實現一個外觀模式,需要將子系統組合進外觀中,然後將工作委託給子系統執行。

裝飾者模式(Decorator Pattern)

名稱
Decorator
結構
設計模式精簡圖冊
動機
動態地給一個物件新增一些額外的職責。就增加功能來說,D e c o r a t o r 模式相比生成子類更為靈活。
適用性
  • 在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責。
  • 處理那些可以撤消的職責。
  • 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充套件,為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。
優點
  • 裝飾者模式可以提供比繼承更多的靈活性
  • 可以通過一種動態的方式來擴充套件一個物件的功能,在執行時選擇不同的裝飾器,從而實現不同的行為。
  • 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一物件,得到功能更為強大的物件。
  • 具體構件類與具體裝飾類可以獨立變化,使用者可以根據需要增加新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有程式碼無須改變,符合“開閉原則”。
缺點
  • 會產生很多的小物件,增加了系統的複雜性
  • 這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易於出錯,排錯也很困難,對於多次裝飾的物件,除錯時尋找錯誤可能需要逐級排查,較為煩瑣。
小結
  • 裝飾者模式意味著一群裝飾者類,這些類用來包裝具體元件
  • 裝飾者可以在被裝飾者的行為前面或者後面加上自己的行為,甚至可以將被裝飾者的行為整個取代掉,從而達到特定的目的。
  • 可以用多個裝飾者包裝一個元件。
  • 裝飾者一般對於元件的客戶是透明的,除非客戶程式依賴於元件的具體型別。
  • 裝飾者會導致設計中出現許多的小物件,如果過度的使用,會讓系統變得更加複雜。
  • 裝飾者和被裝飾者物件有相同的超型別。

組合模式(Composite Pattern)

名稱
Composite
結構
設計模式精簡圖冊
動機
將物件組合成樹形結構以表示?部分-整體?的層次結構。C o m p o s i t e 使得使用者對單個物件和組合物件的使用具有一致性。
適用性
  • 你想表示物件的部分-整體層次結構。
  • 你希望使用者忽略組合物件與單個物件的不同,使用者將統一地使用組合結構中的所有物件。
優點
  • 可以清楚地定義分層次的複雜物件,表示物件的全部或部分層次,使得增加新構件也更容易。
  • 客戶端呼叫簡單,客戶端可以一致的使用組合結構或其中單個物件。
  • 定義了包含葉子物件和容器物件的類層次結構,葉子物件可以被組合成更復雜的容器物件,而這個容器物件又可以被組合,這樣不斷遞迴下去,可以形成複雜的樹形結構。
  • 更容易在組合體內加入物件構件,客戶端不必因為加入了新的物件構件而更改原有程式碼。
缺點
  • 使設計變得更加抽象,物件的業務規則如果很複雜,則實現組合模式具有很大挑戰性,而且不是所有的方法都與葉子物件子類都有關聯,會有冗餘程式碼
小結
  • 組合模式用於將多個物件組合成樹形結構以表示“整體-部分”的結構層次。組合模式對單個物件(葉子物件)和組合物件(容器物件)的使用具有一致性。
  • 組合物件的關鍵在於它定義了一個抽象構建類,它既可表示葉子物件,也可表示容器物件,客戶僅僅需要針對這個抽象構建進行程式設計,無須知道他是葉子物件還是容器物件,都是一致對待。
  • 組合模式雖然能夠非常好地處理層次結構,也使得客戶端程式變得簡單,但是它也使得設計變得更加抽象,而且也很難對容器中的構件型別進行限制,這會導致在增加新的構件時會產生一些問題。

代理模式(Proxy Pattern)

名稱
Proxy
結構
設計模式精簡圖冊
動機
為其他物件提供一種代理以控制對這個物件的訪問。
適用性
  • 不希望某些類被直接訪問。
  • 訪問之前希望先進行一些預處理。
  • 希望對被訪問的物件進行記憶體、許可權等方面的控制。 模式。
優點
  • 代理模式能夠協調呼叫者和被呼叫者,在一定程度上降低了系統的耦合度。
  • 代理物件可以在客戶端和目標物件之間起到中介的作用,這樣起到了的作用和保護了目標物件的
缺點
  • 由於在客戶端和真實主題之間增加了代理物件,因此有些型別的代理模式可能會造成請求的處理速度變慢。
  • 實現代理模式需要額外的工作,有些代理模式的實現非常複雜。
小結
  • 代理模式是通過使用引用代理物件來訪問真實物件,在這裡代理物件充當用於連線客戶端和真實物件的中介者。
  • 代理模式主要用於遠端代理、虛擬代理和保護代理。其中保護代理可以進行訪問許可權控制。

介面卡模式(Adapter Pattern)

名稱
Adapter
結構
設計模式精簡圖冊
        <div data-type="image" data-display="block" data-align="center" data-src="http://www.uml.org.cn/chanpin/intro/WebHelp/Adapter_Class.gif" data-width="543">
          <img src="http://www.uml.org.cn/chanpin/intro/WebHelp/Adapter_Class.gif" width="543" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td rowspan="1" colSpan="1">
      <div data-type="p">動機</div>
    </td>
    <td rowspan="1" colSpan="1">
      <div data-type="p">將一個類的介面轉換成客戶希望的另外一個介面。Adapter 模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。</div>
    </td>
  </tr>
  <tr>
    <td rowspan="1" colSpan="1">
      <div data-type="p">適用性</div>
    </td>
    <td rowspan="1" colSpan="1">
      <ul data-type="unordered-list">
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">你想使用一個已經存在的類,而它的介面不符合你的需求。</div>
        </li>
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">你想建立一個可以複用的類,該類可以與其他不相關的類或不可預見的類(即那些介面可能不一定相容的類)協同工作。</div>
        </li>
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">(僅適用於物件Adapter )你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的介面。物件介面卡可以適配它的父類介面。</div>
        </li>
      </ul>
    </td>
  </tr>
  <tr height="34px">
    <td rowspan="1" colSpan="1">
      <div data-type="p">優點</div>
    </td>
    <td rowspan="1" colSpan="1">
      <ul data-type="unordered-list">
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">將目標類和適配者類解耦,通過使用介面卡讓不相容的介面變成了相容,讓客戶從實現的介面解耦。</div>
        </li>
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">增加了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來說是透明的,而且提高了適配者的複用性。</div>
        </li>
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">靈活性和擴充套件性都非常好在不修改原有程式碼的基礎上增加新的介面卡類,符合“開閉原則”。</div>
        </li>
      </ul>
    </td>
  </tr>
  <tr height="34px">
    <td rowspan="1" colSpan="1">
      <div data-type="p">缺點</div>
    </td>
    <td rowspan="1" colSpan="1">
      <ul data-type="unordered-list">
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">過多地使用介面卡,會讓系統非常零亂,不易整體進行把握。比如,明明看到呼叫的是 A 介面,其實內部被適配成了 B 介面的實現,一個系統如果太多出現這種情況,無異於一場災難。</div>
        </li>
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">因此如果不是很有必要,可以不使用介面卡,而是直接對系統進行重構。</div>
        </li>
      </ul>
    </td>
  </tr>
  <tr height="34px">
    <td rowspan="1" colSpan="1">
      <div data-type="p">小結</div>
    </td>
    <td rowspan="1" colSpan="1">
      <ul data-type="unordered-list">
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">當我們需要使用的一個現有的類,但是他的介面並不符合我們的需求時,我們可以使用介面卡模式。</div>
        </li>
        <li data-type="list-item" data-list-type="unordered-list">
          <div data-type="p">介面卡模式分為類介面卡和物件介面卡,其中類介面卡需要用到多重繼承。</div>
        </li>
      </ul>
    </td>
  </tr>
</tbody>
複製程式碼

結構型設計模式小結

模式 場景發散 一句話說明
橋(Bridge) 麻煩的日誌記錄 將“抽象”和“實現”自由搭配。
輕量(Flyweight) 森林裡的樹太多了 輕鬆地處理“大量”物件。
外觀(Façade) 超級手機 同時提供簡單介面和複雜介面。
裝飾者(Decorator) 星巴克的飲料計較系統 不改變介面但要增強功能。
組合(Composite) 超酷的繪圖軟體 不管你是老子還是兒子,都一樣處理。
代理(Proxy) 找中介租房 代理要控制你的訪問,同時讓你的訪問更舒服 。
介面卡(Adapter) 老掉牙系統的重生 不改變功能但要改變介面

行為型設計模式(類與物件怎樣的互動和分配職責)

觀察者模式(Observer Pattern)

名稱
Observer
結構
設計模式精簡圖冊
動機
定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時, 所有依賴於它的物件都得到通知並被自動更新。
適用性
  • 當一個抽象模型有兩個方面, 其中一個方面依賴於另一方面。將這二者封裝在獨立的物件中以使它們可以各自獨立地改變和複用。
  • 當對一個物件的改變需要同時改變其它物件, 而不知道具體有多少物件有待改變。
  • 當一個物件必須通知其它物件,而它又不能假定其它物件是誰。換言之, 你不希望這些物件是緊密耦合的。
優點
  • 當兩個物件之間送耦合,他們依然可以互動,但是不太清楚彼此的細節。觀察者模式提供了一種物件設計,讓主題和觀察者之間送耦合。主題所知道只是一個具體的觀察者列表,每一個具體觀察者都符合一個抽象觀察者的介面。主題並不認識任何一個具體的觀察者,它只知道他們都有一個共同的介面。
  • 觀察者模式支援“廣播通訊”。主題會向所有的觀察者發出通知。
  • 觀察者模式符合“開閉原則”的要求。
缺點
  • 如果一個被觀察者物件有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
  • 如果在觀察者和觀察目標之間有迴圈依賴的話,觀察目標會觸發它們之間進 行迴圈呼叫,可能導致系統崩潰。
  • 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標物件是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。
小結
  • 觀察者模式定義了物件之間的一對多關係。多個觀察者監聽同一個被觀察者,當該被觀察者的狀態發生改變時,會通知所有的觀察者。
  • 觀察者模式中包含四個角色。主題,它指被觀察的物件。具體主題是主題子類,通常它包含有經常發生改變的資料,當它的狀態發生改變時,向它的各個觀察者發出通知;觀察者,將對觀察主題的改變做出反應;具體觀察者中維護一個指向具體目標物件的引用,它儲存具體觀察者的有關狀態,這些狀態需要和具體目標的狀態保持一致。

策略模式(Strategy Pattern)

名稱
Strategy
結構
設計模式精簡圖冊
動機
定義一系列的演算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得演算法可獨立於使用它的客戶而變化。
適用性
  • 許多相關的類僅僅是行為有異。策略模式提供了一種用多個行為中的一個行為來配置一個類的方法。
  • 需要使用一個演算法的不同變體。
  • 演算法使用客戶不應該知道的資料。可使用策略模式以避免暴露覆雜的、與演算法相關的資料結構。
  • 一個類定義了多種行為, 並且這些行為在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的S t r a t e g y 類中以代替這些條件語句。
優點
  • 策略模式提供了對“開閉原則”的完美支援,使用者可以在不修改原有系統的基礎上選擇演算法或行為,也可以靈活地增加新的演算法或行為。
  • 策略模式提供了可以替換繼承關係的辦法。
  • 使用策略模式可以避免使用多重條件轉移語句。
缺點
  • 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。
  • 策略模式將造成產生很多策略類,
小結
  • 如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,那麼使用策略模式可以動態地讓一個物件在許多行為中選擇一種行為。
  • 一個系統需要動態地在幾種演算法中選擇一種。
  • 如果一個物件有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件選擇語句來實現。

迭代器模式(Iterator Pattern)

名稱
Iterator
結構
設計模式精簡圖冊
動機
提供一種方法順序訪問一個聚合物件中各個元素, 而又不需暴露該物件的內部表示。
適用性
  • 訪問一個聚合物件的內容而無需暴露它的內部表示。
  • 支援對聚合物件的多種遍歷。
  • 為遍歷不同的聚合結構提供一個統一的介面(即, 支援多型迭代)。
優點
  • 它支援以不同的方式遍歷一個聚合物件。
  • 迭代器簡化了聚合類。
  • 在同一個聚合上可以有多個遍歷。
  • 在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有程式碼。
缺點
  • 由於迭代器模式將儲存資料和遍歷資料的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
小結
  • 將遍歷聚合物件中資料的行為提取出來,封裝到一個迭代器中,通過專門的迭代器來遍歷聚合物件的內部資料,這就是迭代器模式的本質。迭代器模式是“單一職責原則”的完美體現。
  • 當使用迭代器的時候,我們依賴聚合提供遍歷。
  • 迭代器提供了一個通用的介面,讓我們遍歷聚合的項,放我們編碼使用聚合項時,就可以使用多型機制。

命令模式(Command Pattern)

名稱
Command
結構
設計模式精簡圖冊
動機
將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化;對請求排隊或記錄請求日誌,以及支援可撤消的操作。
適用性
  • 抽象出待執行的動作以引數化某物件,你可用過程語言中的回撥(c a l l b a c k )函式表達這種引數化機制。所謂回撥函式是指函式先在某處註冊,而它將在稍後某個需要的時候被呼叫。C o m m a n d 模式是回撥機制的一個物件導向的替代品。
  • 在不同的時刻指定、排列和執行請求。一個C o m m a n d 物件可以有一個與初始請求無關的生存期。如果一個請求的接收者可用一種與地址空間無關的方式表達,那麼就可將負責該請求的命令物件傳送給另一個不同的程式並在那兒實現該請求。
  • 支援取消操作。C o m m a n d 的E x c u t e 操作可在實施操作前將狀態儲存起來,在取消操作時這個狀態用來消除該操作的影響。C o m m a n d 介面必須新增一個U n e x e c u t e 操作,該操作取消上一次E x e c u t e 呼叫的效果。執行的命令被儲存在一個歷史列表中。可通過向後和向前遍歷這一列表並分別呼叫U n e x e c u t e 和E x e c u t e 來實現重數不限的取消和重做。
  • 支援修改日誌,這樣當系統崩潰時,這些修改可以被重做一遍。在C o m m a n d 介面中新增裝載操作和儲存操作,可以用來保持變動的一個一致的修改日誌。從崩潰中恢復的過程包括從磁碟中重新讀入記錄下來的命令並用E x e c u t e 操作重新執行它們。
  • 用構建在原語操作上的高層操作構造一個系統。這樣一種結構在支援事務( t r a n s a c t i o n )的資訊系統中很常見。一個事務封裝了對資料的一組變動。C o m m a n d 模式提供了對事務進行建模的方法。C o m m a n d 有一個公共的介面,使得你可以用同一種方式呼叫所有的事務。同時使用該模式也易於新增新事務以擴充套件系統。
優點
  • 降低了系統耦合度
  • 新的命令可以很容易新增到系統中去。
缺點
  • 使用命令模式可能會導致某些系統有過多的具體命令類。
小結
  • 命令模式的本質就是將命令物件進行封裝打包,將發出命令的責任和執行命令的責任進行割開。
  • 命令模式中傳送者只需要知道如何傳送請求命令,無須關心命令執行具體過程。
  • 在傳送者和接收者兩者間是通過命令物件進行溝通的。請求命令本身就當做一個物件在兩者間進行傳遞,它封裝了接收者和一組動作。
  • 命令模式支援撤銷。
  • 命令模式佇列請求和日誌請求。

訪問者模式(Visitor Pattern)

名稱
Visitor
結構
設計模式精簡圖冊
動機
表示一個作用於某物件結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
適用性
  • 一個物件結構包含很多類物件,它們有不同的介面,而你想對這些物件實施一些依賴於其具體類的操作。
  • 需要對一個物件結構中的物件進行很多不同的並且不相關的操作,而你想避免讓這些操作?汙染?這些物件的類。Vi s i t o r 使得你可以將相關的操作集中起來定義在一個類中。當該物件結構被很多應用共享時,用Vi s i t o r 模式讓每個應用僅包含需要用到的操作。
  • 定義物件結構的類很少改變,但經常需要在此結構上定義新的操作。改變物件結構類需要重定義對所有訪問者的介面,這可能需要很大的代價。如果物件結構類經常改變,那麼可能還是在這些類中定義這些操作較好。
優點
  • 使得新增新的訪問操作變得更加簡單。
  • 能夠使得使用者在不修改現有類的層次結構下,定義該類層次結構的操作。
  • 將有關元素物件的訪問行為集中到一個訪問者物件中,而不是分散搞一個個的元素類中。
缺點
  • 增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類都意味著要在抽象訪問者角色中增加一個新的抽象操作,並在每一個具體訪問者類中增加相應的具體操作,違背了“開閉原則”的要求。
  • 破壞封裝。當採用訪問者模式的時候,就會打破組合類的封裝。
小結
  • 1.SomeClass 的 Accept()方法就是訪問原來類的小口, Accept()方法只有一句程式碼,就是: visitor.NewMethod(this) ,這是訪問者模式的精妙之處。 2.SomeClass 的新功能通過實現 IVisitor 介面的類來實現。
  • 訪問者模式封裝了物件結構元素之上的操作,使得新增元素的操作變得非常簡單。所以它比較適用於那麼物件結構很少變化的類。
  • 訪問者模式中物件結構儲存了不同型別的元素物件,以供不同訪問者訪問。

直譯器模式(Interpreter Pattern)

名稱
Interpreter
結構
設計模式精簡圖冊
動機
給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。
適用性
  • 當有一個語言需要解釋執行, 並且你可將該語言中的句子表示為一個抽象語法樹時,可使用直譯器模式。而當存在以下情況時該模式效果最好:
  • 該文法簡單對於複雜的文法, 文法的類層次變得龐大而無法管理。此時語法分析程式生成器這樣的工具是更好的選擇。它們無需構建抽象語法樹即可解釋表示式, 這樣可以節省空間而且還可能節省時間。
  • 效率不是一個關鍵問題最高效的直譯器通常不是通過直接解釋語法分析樹實現的, 而是首先將它們轉換成另一種形式。例如,正規表示式通常被轉換成狀態機。但即使在這種情況下, 轉換器仍可用直譯器模式實現, 該模式仍是有用的。
優點
  • 可擴充套件性比較好,靈活。
  • 增加了新的解釋表示式的方式。
  • 易於實現文法。
缺點
  • 執行效率比較低,可利用場景比較少。
  • 對於複雜的文法比較難維護。
小結
  • 在直譯器模式中由於語法是由很多類表示的,所以可擴充套件性強。
  • 雖然直譯器的可擴充套件性強,但是如果語法規則的數目太大的時候,該模式可能就會變得異常複雜。所以直譯器模式適用於文法較為簡單的。
  • 直譯器模式可以處理指令碼語言和程式語言。常用於解決某一特定型別的問題頻繁發生情況。

中介者模式(Mediator Pattern)

名稱
Mediator
結構
設計模式精簡圖冊
動機
用一箇中介物件來封裝一系列的物件互動。中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。
適用性
  • 一組物件以定義良好但是複雜的方式進行通訊。產生的相互依賴關係結構混亂且難以理解。
  • 一個物件引用其他很多物件並且直接與這些物件通訊,導致難以複用該物件。
  • 想定製一個分佈在多個類中的行為,而又不想生成太多的子類。
優點
  • 簡化了物件之間的關係,將系統的各個物件之間的相互關係進行封裝,將各個同事類解耦,使系統成為鬆耦合系統。
  • 減少了子類的生成。
  • 可以減少各同事類的設計與實現。
缺點
  • 由於中介者物件封裝了系統中物件之間的相互關係,導致其變得非常複雜,使得系統維護比較困難。
小結
  • 每個控制元件不需要直接和別的控制元件打交道,只需要知道中介者就可以了。
  • 每個控制元件都需要保持保持中介者的引用,而中介者不一定需要保持每個控制元件的引用
  • Mediator 的程式碼可能很複雜。

備忘錄模式(Memento Pattern)

名稱
Mediator
結構
設計模式精簡圖冊
動機
用一箇中介物件來封裝一系列的物件互動。中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。
適用性
  • 一組物件以定義良好但是複雜的方式進行通訊。產生的相互依賴關係結構混亂且難以理解。
  • 一個物件引用其他很多物件並且直接與這些物件通訊,導致難以複用該物件。
  • 想定製一個分佈在多個類中的行為,而又不想生成太多的子類。
優點
  • 給使用者提供了一種可以恢復狀態的機制。可以是使用者能夠比較方便地回到某個歷史的狀態。
  • 實現了資訊的封裝。使得使用者不需要關心狀態的儲存細節。
缺點
  • 消耗資源。如果類的成員變數過多,勢必會佔用比較大的資源,而且每一次儲存都會消耗一定的記憶體。
小結
  • 到需要儲存物件多個狀態,並且可以恢復到任意狀態,可考慮備忘錄模式。
  • 將物件、物件狀態和狀態的儲存辦法分離,設計上會更加靈活。
  • 但物件屬性的備份、恢復、儲存等動作,都是可能比較耗時的。
  • 備忘錄模式只是提供了儲存物件狀態的一種解決方案框架 ,真正應用時還需要解決這些 問題:1.如何設計 Memento? 2.怎樣儲存多個物件? 3.怎樣儲存組織成樹結構的多個物件?

模板方法模式(TemplateMethod Pattern)

名稱
Template Method
結構
設計模式精簡圖冊
動機
定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。Te m p l a t e M e t h o d 使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
適用性
  • 演算法的骨架是不變的,但其中的步驟實現可能有變化,這時可應用模板方法。
優點
  • 模板方法模式在定義了一組演算法,將具體的實現交由子類負責。
  • 模板方法模式是一種程式碼複用的基本技術。
  • 模板方法模式導致一種反向的控制結構,通過一個父類呼叫其子類的操作,通過對子類的擴充套件增加新的行為,符合“開閉原則”。
缺點
  • 每一個不同的實現都需要一個子類來實現,導致類的個數增加,是的系統更加龐大。
小結
  • 模板方法模式定義了演算法的步驟,將這些步驟的實現延遲到了子類。
  • 模板方法模式為我們提供了一種程式碼複用的重要技巧。
  • 模板方法模式的抽象類可以定義抽象方法、具體方法和鉤子。
  • 為了防止子類改變演算法的實現步驟,我們可以將模板方法宣告為final。

狀態模式(State Pattern)

名稱
State
結構
設計模式精簡圖冊
動機
允許一個物件在其內部狀態改變時改變它的行為。物件看起來似乎修改了它的類。
適用性
  • 一個物件的行為取決於它的狀態, 並且它必須在執行時刻根據狀態改變它的行為。
  • 一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該物件的狀態。這個狀態通常用一個或多個列舉常量表示。通常, 有多個操作包含這一相同的條件結構。S t a t e模式將每一個條件分支放入一個獨立的類中。這使得你可以根據物件自身的情況將物件的狀態作為一個物件,這一物件可以不依賴於其他物件而獨立變化。
優點
  • 封裝了轉換規則。
  • 列舉可能的狀態,在列舉狀態之前需要確定狀態種類。
  • 將所有與某個狀態有關的行為放到一個類中,並且可以方便地增加新的狀態,只需要改變物件狀態即可改變物件的行為。
  • 允許狀態轉換邏輯與狀態物件合成一體,而不是某一個巨大的條件語句塊。
  • 可以讓多個環境物件共享一個狀態物件,從而減少系統中物件的個數。
缺點
  • 狀態模式的使用必然會增加系統類和物件的個數。
  • 狀態模式的結構與實現都較為複雜,如果使用不當將導致程式結構和程式碼的混亂。
  • 狀態模式對“開閉原則”的支援並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的原始碼,否則無法切換到新增狀態;而且修改某個狀態類的行為也需修改對應類的原始碼。
小結
  • 狀態模式允許一個物件基於內部狀態而擁有不同的行為。
  • Context會將行為委託給當前狀態物件。
  • 狀態模式對“開閉原則”支援不是很好。

責任鏈模式(Chain of Responsibility Pattern)

名稱
Chain of Responsibility
結構
設計模式精簡圖冊
動機
使多個物件都有機會處理請求,從而避免請求的傳送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止。
適用性
  • 有多個的物件可以處理一個請求,哪個物件處理該請求執行時刻自動確定。
  • 你想在不明確指定接收者的情況下,向多個物件中的一個提交一個請求。
  • 可處理一個請求的物件集合應被動態指定。
優點
  • 降低耦合度。它將請求的傳送者和接受者解耦。
  • 簡化了物件。使得物件不需要知道鏈的結構。
  • 增強給物件指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。
  • 增加新的請求處理類很方便。
缺點
  • 不能保證請求一定被接收。
  • 系統效能將受到一定影響,而且在進行程式碼除錯時不太方便;可能會造成迴圈呼叫
  • 可能不容易觀察執行時的特徵,有礙於除錯。
小結
  • 職責鏈模式將請求的傳送者和接受者解耦了。客戶端不需要知道請求處理者的明確資訊,甚至不需要知道鏈的結構,它只需要將請求進行傳送即可。
  • 職責鏈模式能夠非常方便的動態增加新職責或者刪除職責。
  • 客戶端傳送的請求可能會得不到處理。
  • 處理者不需要知道鏈的結構,只需要明白他的後續者是誰就可以了。這樣就簡化了系統中的物件。

行為型設計模式小結

模式 場景發散 一句話說明
觀察者(Observer) 同步更新的問題 一呼百應。
策略(Strategy) 設計你的戰士 分離演算法。
迭代器(Iterator) 集合訪問的煩惱 以一致的方式訪問集合, “鬆綁 ”遍歷演算法程式碼。
命令(Command) 神奇的Do與Undo 分離功能呼叫者與功能實現者。
訪問者(Visitor) 增加新方法的煩惱 不改變物件結構增加新方法。
直譯器(Interpreter) 超級表達解釋引擎 語法解釋。
中介者(Mediator) 麻煩的多角關係 處理多對多關係。
備忘錄(Memento) 假如一切可以重來 儲存物件的多個狀態並可任意恢復。
模板方法(Template Method) 萬能的排序器 定義好框架演算法 ,某些步驟可自己定義 。
狀態(State) 是攻擊還是逃走 方便地處理不同狀態不同行為,以及狀態之間的轉換。
責任鏈(Chain) 郵件自動處理系統 用不同的規則去處理請求。

模式比較

參考

公眾號小.jpg

相關文章