天天看點

23種設計模式整體詳解

    設計模式分為23種,每種都不是獨立的,每種間都有聯系:

23種設計模式整體詳解
下面從意圖和使用性兩方面較長的描述每一種設計模式。

1.工廠模式(Factory)

23種設計模式整體詳解

意圖

定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類。Factory Method 使一個類的執行個體化延遲到其子類。

适用性

  • 當一個類不知道它所必須建立的對象的類的時候。
  • 當一個類希望由它的子類來指定它所建立的對象的時候。
  • 當類将建立對象的職責委托給多個幫助子類中的某一個,并且你希望将哪一個幫助子類是代理者這一資訊局部化的時候。

2.抽象工廠模式(Abstract Factory)

23種設計模式整體詳解

提供一個建立一系列相關或互相依賴對象的接口,而無需指定它們具體的類。

  • 一個系統要獨立于它的産品的建立、組合和表示時。
  • 一個系統要由多個産品系列中的一個來配置時。
  • 當你要強調一系列相關的産品對象的設計以便進行聯合使用時。
  • 當你提供一個産品類庫,而隻想顯示它們的接口而不是實作時。

3.建造者模式

23種設計模式整體詳解

将一個複雜對象的建構與它的表示分離,使得同樣的建構過程可以建立不同的表示。

  • 當建立複雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時。
  • 當構造過程必須允許被構造的對象有不同的表示時。

4.原型模式

23種設計模式整體詳解

用原型執行個體指定建立對象的種類,并且通過拷貝這些原型建立新的對象。

  • 當要執行個體化的類是在運作時刻指定時,例如,通過動态裝載;或者
  • 為了避免建立一個與産品類層次平行的工廠類層次時;或者
  • 當一個類的執行個體隻能有幾個不同狀态組合中的一種時。建立相應數目的原型并克隆它們可能比每次用合适的狀态手工執行個體化該類更友善一些。

5.單例模式

23種設計模式整體詳解

保證一個類僅有一個執行個體,并提供一個通路它的全局通路點。

  • 當類隻能有一個執行個體而且客戶可以從一個衆所周知的通路點通路它時。
  • 當這個唯一執行個體應該是通過子類化可擴充的,并且客戶應該無需更改代碼就能使用一個擴充的執行個體時。

6.擴充卡模式

23種設計模式整體詳解

将一個類的接口轉換成另外一個客戶希望的接口。Adapter 模式使得原本由于接口不相容而不能一起工作的那些類可以一起工作。

  • 你想使用一個已經存在的類,而它的接口不符合你的需求。
  • 你想建立一個可以複用的類,該類可以與其他不相關的類或不可預見的類(即那些接口可能不一定相容的類)協同工作。
  • (僅适用于對象Adapter)你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以比對它們的接口。對象擴充卡可以适配它的父類接口。

7.橋接模式

23種設計模式整體詳解

将抽象部分與它的實作部分分離,使它們都可以獨立地變化。

  • 你不希望在抽象和它的實作部分之間有一個固定的綁定關系。例如這種情況可能是因為,在程式運作時刻實作部分應可以被選擇或者切換。
  • 類的抽象以及它的實作都應該可以通過生成子類的方法加以擴充。這時B r i d g e 模式使你可以對不同的抽象接口和實作部分進行組合,并分别對它們進行擴充。
  • 對一個抽象的實作部分的修改應對客戶不産生影響,即客戶的代碼不必重新編譯。
  • (C++)你想對客戶完全隐藏抽象的實作部分。在C++中,類的表示在類接口中是可見的。
  • 有許多類要生成。這樣一種類層次結構說明你必須将一個對象分解成兩個部分。Rumbaugh稱這種類層次結構為“嵌套的普化”(nested generalizations )。
  • 你想在多個對象間共享實作(可能使用引用計數),但同時要求客戶并不知道這一點。一個簡單的例子便是Coplien的String類,在這個類中多個對象可以共享同一個字元串表示(StringRep)。

8.組合模式

23種設計模式整體詳解

将對象組合成樹形結構以表示“部分-整體”的層次結構。C o m p o s i t e 使得使用者對單個對象群組合對象的使用具有一緻性。

  • 你想表示對象的部分—整體層次結構。
  • 你希望使用者忽略組合對象與單個對象的不同,使用者将統一地使用組合結構中的所有對象。

9.裝飾模式

23種設計模式整體詳解

動态地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。

  • 在不影響其他對象的情況下,以動态、透明的方式給單個對象添加職責。
  • 處理那些可以撤消的職責。
  • 當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充,為支援每一種組合将産生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隐藏,或類定義不能用于生成子類。

10.門面模式

23種設計模式整體詳解

為子系統中的一組接口提供一個一緻的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

  • 你要為一個複雜子系統提供一個簡單接口時。子系統往往因為不斷演化而變得越來越複雜。大多數模式使用時都會産生更多更小的類。這使得子系統更具可重用性,

    也更容易對子系統進行定制,但這也給那些不需要定制子系統的使用者帶來一些使用上的困難。Facade可以提供一個簡單的預設視圖,這一視圖對大多數使用者來

    說已經足夠,而那些需要更多的可定制性的使用者可以越過Facade層。

  • 客戶程式與抽象類的實作部分之間存在着很大的依賴性。引入Facade将這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
  • 當你需要建構一個層次結構的子系統時,使用門面模式定義子系統中每層的入口點。如果子系統之間是互相依賴的,你可以讓它們僅通過Facade進行通訊,進而簡化了它們之間的依賴關系。

11.享元模式

23種設計模式整體詳解

運用共享技術有效地支援大量細粒度的對象。

  • 一個應用程式使用了大量的對象。
  • 完全由于使用大量的對象,造成很大的存儲開銷。
  • 對象的大多數狀态都可變為外部狀态。
  • 如果删除對象的外部狀态,那麼可以用相對較少的共享對象取代很多組對象。
  • 應用程式不依賴于對象辨別。由于Flyweight對象可以被共享,對于概念上明顯有别的對象,辨別測試将傳回真值。

12.代理模式

23種設計模式整體詳解

為其他對象提供一種代理以控制對這個對象的通路。

在需要用比較通用和複雜的對象指針代替簡單的指針的時候,使用Proxy模式。下面是一 些可以使用Proxy模式常見情況:

  1. 遠端代理(Remote Proxy)為一個對象在不同的位址空間提供局部代表。
  2. 虛代理(Virtual Proxy)根據需要建立開銷很大的對象。
  3. 保護代理(Protection Proxy)控制對原始對象的通路。保護代理用于對象應該有不同 的通路權限的時候。
  4. 智能指引(Smart Reference)取代了簡單的指針,它在通路對象時執行一些附加操作。 它的典型用途包括:
  • 對指向實際對象的引用計數,這樣當該對象沒有引用時,可以自動釋放它(也稱為SmartPointers)。
  • 當第一次引用一個持久對象時,将它裝入記憶體。
  • 在通路一個實際對象前,檢查是否已經鎖定了它,以確定其他對象不能改變它。

13.職責鍊模式

23種設計模式整體詳解

使多個對象都有機會處理請求,進而避免請求的發送者和接收者之間的耦合關系。将這些對象連成一條鍊,并沿着這條鍊傳遞該請求,直到有一個對象處理它為止。

  • 有多個的對象可以處理一個請求,哪個對象處理該請求運作時刻自動确定。
  • 你想在不明确指定接收者的情況下,向多個對象中的一個送出一個請求。
  • 可處理一個請求的對象集合應被動态指定。

14.指令模式

23種設計模式整體詳解

将一個請求封裝為一個對象,進而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支援可取消的操作

  • 上面讨論的MenuItem對象那樣,抽象出待執行的動作以參數化某對象。你可用過程語言中的回調(callback)函數表達這種參數化機制。所謂回調

    函數是指函數先在某處注冊,而它将在稍後某個需要的時候被調用。Command模式是回調機制的一個面向對象的替代品。

  • 在不同的時刻指定、排列和執行請求。一個Command對象可以有一個與初始請求無關的生存期。如果一個請求的接收者可用一種與位址空間無關的方式表達,那麼就可将負責該請求的指令對象傳送給另一個不同的程序并在那兒實作該請求。
  • 支援取消操作。

    Command的Execute操作可在實施操作前将狀态存儲起來,在取消操作時這個狀态用來消除該操作的影響。Command接口必須添加一個

    Execute操作,該操作取消上一次Execute調用的效果。執行的指令被存儲在一個曆史清單中。可通過向後和向前周遊這一清單并分别調用

    Unexecute和Execute來實作重數不限的“取消”和“重做”。

  • 支援修改日志,這樣當系統崩潰時,這些修改可以被重做一遍。在Command接口中添加裝載操作和存儲操作,可以用來保持變動的一個一緻的修改日志。從崩潰中恢複的過程包括從磁盤中重新讀入記錄下來的指令并用Execute操作重新執行它們。
  • 用建構在原語操

    作上的高層操作構造一個系統。這樣一種結構在支援事務(Transaction)的資訊系統中很常見。一個事務封裝了對資料的一組變動。Command模

    式提供了對事務進行模組化的方法。Command有一個公共的接口,使得你可以用同一種方式調用所有的事務。同時使用該模式也易于添加新事務以擴充系統。

15.解析器模式

23種設計模式整體詳解

給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。

  • 當有一個語言需要解釋執行, 并且你可将該語言中的句子表示為一個抽象文法樹時,可使用解釋器模式。而當存在以下情況時該模式效果最好:
    • 該文法簡單對于複雜的文法, 文法的類層次變得龐大而無法管理。此時文法分析程式生成器這樣的工具是更好的選擇。它們無需建構抽象文法樹即可解釋表達式, 這樣可以節省空間而且還可能節省時間。
    • 效率不是一個關鍵問題最高效的解釋器通常不是通過直接解釋文法分析樹實作的, 而是首先将它們轉換成另一種形式。例如,正規表達式通常被轉換成狀态機。但即使在這種情況下, 轉換器仍可用解釋器模式實作, 該模式仍是有用的。

16.疊代器模式

23種設計模式整體詳解

提供一種方法順序通路一個聚合對象中各個元素, 而又不需暴露該對象的内部表示。

  • 通路一個聚合對象的内容而無需暴露它的内部表示。
  • 支援對聚合對象的多種周遊。
  • 為周遊不同的聚合結構提供一個統一的接口(即, 支援多态疊代)。

17.中介模式

23種設計模式整體詳解

用一個中介對象來封裝一系列的對象互動。中介者使各對象不需要顯式地互相引用,進而使其耦合松散,而且可以獨立地改變它們之間的互動。

  • 一組對象以定義良好但是複雜的方式進行通信。産生的互相依賴關系結構混亂且難以了解。
  • 一個對象引用其他很多對象并且直接與這些對象通信,導緻難以複用該對象。
  • 想定制一個分布在多個類中的行為,而又不想生成太多的子類。

18.備忘錄模式

23種設計模式整體詳解

在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。這樣以後就可将該對象恢複到儲存的狀态。

  • 必須儲存一個對象在某一個時刻的(部分)狀态, 這樣以後需要時它才能恢複到先前的狀态。
  • 如果一個用接口來讓其它對象直接得到這些狀态,将會暴露對象的實作細節并破壞對象的封裝性。

19.觀察者模式

23種設計模式整體詳解

定義對象間的一種一對多的依賴關系,當一個對象的狀态發生改變時, 所有依賴于它的對象都得到通知并被自動更新。

  • 當一個抽象模型有兩個方面, 其中一個方面依賴于另一方面。将這二者封裝在獨立的對象中以使它們可以各自獨立地改變和複用。
  • 當對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。
  • 當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊密耦合的。

20.狀态模式

23種設計模式整體詳解

允許一個對象在其内部狀态改變時改變它的行為。對象看起來似乎修改了它的類。

  • 一個對象的行為取決于它的狀态, 并且它必須在運作時刻根據狀态改變它的行為。
  • 一個操作中含有

    龐大的多分支的條件語句,且這些分支依賴于該對象的狀态。這個狀态通常用一個或多個枚舉常量表示。通常,

    有多個操作包含這一相同的條件結構。State模式将每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況将對象的狀态作為一個對象,這一

    對象可以不依賴于其他對象而獨立變化。

21.政策模式

23種設計模式整體詳解

定義一系列的算法,把它們一個個封裝起來, 并且使它們可互相替換。本模式使得算法可獨立于使用它的客戶而變化。

  • 許多相關的類僅僅是行為有異。“政策”提供了一種用多個行為中的一個行為來配置一個類的方法。
  • 需要使用一個算法的不同變體。例如,你可能會定義一些反映不同的空間/時間權衡的算法。當這些變體實作為一個算法的類層次時,可以使用政策模式。
  • 算法使用客戶不應該知道的資料。可使用政策模式以避免暴露複雜的、與算法相關的資料結構。
  • 一個類定義了多種行為, 并且這些行為在這個類的操作中以多個條件語句的形式出現。将相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。

22.模版模式

23種設計模式整體詳解

定義一個操作中的算法的骨架,而将一些步驟延遲到子類中。Te m p l a t e M e t h o d 使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

  • 一次性實作一個算法的不變的部分,并将可變的行為留給子類來實作。
  • 各子類中公共的

    行為應被提取出來并集中到一個公共父類中以避免代碼重複。這是Opdyke和Johnson所描述過的“重分解以一般化”的一個很好的例子。首先識别現有

    代碼中的不同之處,并且将不同之處分離為新的操作。最後,用一個調用這些新的操作的模闆方法來替換這些不同的代碼。

  • 控制子類擴充。模闆方法隻在特定點調用“hook”操作,這樣就隻允許在這些點進行擴充。

23.通路者模式

23種設計模式整體詳解

表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

繼續閱讀