設計模式分爲三種類型,共23種。
-
創建型模式:單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。
-
結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
-
行爲型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、職責鏈模式、訪問者模式。
按字典序排列簡介如下。
Abstract Factory(
抽象工廠模式):提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
Adapter(
適配器模式):將一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
Bridge(
橋接模式):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
Builder(
建造者模式):將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
Chain of Responsibility(職責鏈模式):爲解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它。
Command(
命令模式):將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作。
Composite(
組合模式):將對象組合成樹形結構以表示“部分-整體”的層次結構。它使得客戶對單個對象和複合對象的使用具有一致性。
Decorator(
裝飾模式):動態地給一個對象添加一些額外的職責。就擴展功能而言, 它比生成子類方式更爲靈活。
Facade(
外觀模式):爲子系統中的一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
Factory Method(
工廠模式):定義一個用於創建對象的接口,讓子類決定將哪一個類實例化。Factory Method使一個類的實例化延遲到其子類。
Flyweight(
享元模式):運用共享技術有效地支持大量細粒度的對象。
Interpreter(解析器模式):給定一個語言, 定義它的文法的一種表示,並定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。
Iterator(
迭代器模式):提供一種方法順序訪問一個聚合對象中各個元素,而又不需暴露該對象的內部表示。
Mediator(
中介模式):用一箇中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
Memento(
備忘錄模式):在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
Observer(
觀察者模式):定義對象間的一種一對多的依賴關係,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動刷新。
Prototype(
原型模式):用原型實例指定創建對象的種類,並且通過拷貝這個原型來創建新的對象。
Proxy(
代理模式):爲其他對象提供一個代理以控制對這個對象的訪問。
Singleton(
單例模式):保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。 單例模式是最簡單的設計模式之一,但是對於Java的開發者來說,它卻有很多缺陷。在九月的專欄中,David Geary探討了單例模式以及在面對多線程(multi-threading)、類裝載器(class loaders)和序列化(serialization)時如何處理這些缺陷。
State(
狀態模式):允許一個對象在其內部狀態改變時改變它的行爲。對象看起來似乎修改了它所屬的類。
Strategy(
策略模式):定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得算法的變化可獨立於使用它的客戶。
Template Method(模板方法模式):定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
Visitor(
訪問者模式):表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
從下一節開始,詳細描述以下每一種設計模式。
工廠模式(Factory)
工廠模式(Factory)
意圖
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。
適用性
抽象工廠模式(Abstract Factory)
抽象工廠模式(Abstract Factory)
意圖
提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
適用性
建造者模式(Builder)
意圖
建造者模式
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
適用性
原型模式(Prototype)
意圖
原型模式
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
適用性
-
當要實例化的類是在運行時刻指定時,例如,通過動態裝載;或者
-
爲了避免創建一個與產品類層次平行的工廠類層次時;或者
-
當一個類的實例只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工實例化該類更方便一些。
單例模式(Singleton)
意圖
單例模式
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
適用性
適配器模式(Adapter)
意圖
適配器模式
將一個類的接口轉換成另外一個客戶希望的接口。A d a p t e r 模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
適用性
-
你想使用一個已經存在的類,而它的接口不符合你的需求。
-
你想創建一個可以複用的類,該類可以與其他不相關的類或不可預見的類(即那些接口可能不一定兼容的類)協同工作。
-
(僅適用於對象Adapter)你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口。
橋接模式(Bridge)
意圖
橋接模式
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
適用性
-
你不希望在抽象和它的實現部分之間有一個固定的綁定關係。例如這種情況可能是因爲,在程序運行時刻實現部分應可以被選擇或者切換。
-
類的抽象以及它的實現都應該可以通過生成子類的方法加以擴充。這時B r i d g e 模式使你可以對不同的抽象接口和實現部分進行組合,並分別對它們進行擴充。
-
對一個抽象的實現部分的修改應對客戶不產生影響,即客戶的代碼不必重新編譯。
-
(
C++)你想對客戶完全隱藏抽象的實現部分。在
C++中,類的表示在類接口中是可見的。
-
有許多類要生成。這樣一種類層次結構說明你必須將一個對象分解成兩個部分。Rumbaugh稱這種類層次結構爲“嵌套的普化”(nested generalizations )。
-
你想在多個對象間共享實現(可能使用引用計數),但同時要求客戶並不知道這一點。一個簡單的例子便是Coplien的String類,在這個類中多個對象可以共享同一個字符串表示(StringRep)。
組合模式(Composite)
意圖
組合模式
將對象組合成樹形結構以表示“部分-整體”的層次結構。C o m p o s i t e 使得用戶對單個對象和組合對象的使用具有一致性。
適用性
裝飾模式(Decorator)
意圖
裝飾模式
動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更爲靈活。
適用性
門面模式(Facade)
意圖
門面模式
爲子系統中的一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
適用性
-
當你要爲一個複雜子系統提供一個簡單接口時。子系統往往因爲不斷演化而變得越來越複雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的用戶帶來一些使用上的困難。Facade可以提供一個簡單的缺省視圖,這一視圖對大多數用戶來說已經足夠,而那些需要更多的可定製性的用戶可以越過Facade層。
-
客戶程序與抽象類的實現部分之間存在着很大的依賴性。引入Facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
-
當你需要構建一個層次結構的子系統時,使用門面模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過Facade進行通訊,從而簡化了它們之間的依賴關係。
享元模式(Flyweight)
意圖
享元模式
運用共享技術有效地支持大量細粒度的對象。
適用性
代理模式(Proxy)
意圖
代理模式
爲其他對象提供一種代理以控制對這個對象的訪問。
適用性
在需要用比較通用和複雜的對象指針代替簡單的指針的時候,使用Proxy模式。下面是一 些可以使用Proxy模式常見情況:
-
遠程代理(Remote Proxy)爲一個對象在不同的地址空間提供局部代表。
-
虛代理(Virtual Proxy)根據需要創建開銷很大的對象。
-
保護代理(Protection Proxy)控制對原始對象的訪問。保護代理用於對象應該有不同 的訪問權限的時候。
-
智能指引(Smart Reference)取代了簡單的指針,它在訪問對象時執行一些附加操作。 它的典型用途包括:
職責鏈模式(Chain of Responsibility)
意圖
職責鏈模式
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的
耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。
適用性
命令模式(Command)
意圖
命令模式
將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作
適用性
-
像上面討論的MenuItem對象那樣,抽象出待執行的動作以參數化某對象。你可用過程語言中的回調(callback)函數表達這種參數化機制。所謂回調函數是指函數先在某處註冊,而它將在稍後某個需要的時候被調用。Command模式是回調機制的一個面向對象的替代品。
-
在不同的時刻指定、排列和執行請求。一個Command對象可以有一個與初始請求無關的生存期。如果一個請求的接收者可用一種與地址空間無關的方式表達,那麼就可將負責該請求的命令對象傳送給另一個不同的進程並在那兒實現該請求。
-
支持取消操作。Command的Execute操作可在實施操作前將狀態存儲起來,在取消操作時這個狀態用來消除該操作的影響。Command接口必須添加一個Execute操作,該操作取消上一次Execute調用的效果。執行的命令被存儲在一個歷史列表中。可通過向後和向前遍歷這一列表並分別調用Unexecute和Execute來實現重數不限的“取消”和“重做”。
-
支持修改日誌,這樣當系統崩潰時,這些修改可以被重做一遍。在Command接口中添加裝載操作和存儲操作,可以用來保持變動的一個一致的修改日誌。從崩潰中恢復的過程包括從磁盤中重新讀入記錄下來的命令並用Execute操作重新執行它們。
-
用構建在原語操作上的高層操作構造一個系統。這樣一種結構在支持事務(Transaction)的信息系統中很常見。一個事務封裝了對數據的一組變動。Command模式提供了對事務進行建模的方法。Command有一個公共的接口,使得你可以用同一種方式調用所有的事務。同時使用該模式也易於添加新事務以擴展系統。
解析器模式(Interpreter)
意圖
解析器模式
給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
適用性
迭代器模式(Iterator)
意圖
迭代器模式
提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。
適用性
中介模式(Mediator)
意圖
中介模式
用一箇中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
適用性
-
一組對象以定義良好但是複雜的方式進行通信。產生的相互依賴關係結構混亂且難以理解。
-
一個對象引用其他很多對象並且直接與這些對象通信,導致難以複用該對象。
-
想定製一個分佈在多個類中的行爲,而又不想生成太多的子類。
備忘錄模式(Memento)
意圖
備忘錄模式
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
適用性
觀察者模式(Observer)
意圖
觀察者模式
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時, 所有依賴於它的對象都得到通知並被自動更新。
適用性
-
當一個抽象模型有兩個方面, 其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和複用。
-
當對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。
-
當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊密耦合的。
狀態模式(State)
意圖
狀態模式
允許一個對象在其內部狀態改變時改變它的行爲。對象看起來似乎修改了它的類。
適用性
-
一個對象的行爲取決於它的狀態, 並且它必須在運行時刻根據狀態改變它的行爲。
-
一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常, 有多個操作包含這一相同的條件結構。State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作爲一個對象,這一對象可以不依賴於其他對象而獨立變化。
策略模式(Strategy)
意圖
策略模式
定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。
適用性
-
許多相關的類僅僅是行爲有異。“策略”提供了一種用多個行爲中的一個行爲來配置一個類的方法。
-
需要使用一個算法的不同變體。例如,你可能會定義一些反映不同的空間/時間權衡的算法。當這些變體實現爲一個算法的類層次時,可以使用策略模式。
-
算法使用客戶不應該知道的數據。可使用策略模式以避免暴露覆雜的、與算法相關的
數據結構。
-
一個類定義了多種行爲, 並且這些行爲在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。
模版模式(Template)
意圖
模板模式
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。Te m p l a t e M e t h o d 使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
適用性
-
一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現。
-
各子類中公共的行爲應被提取出來並集中到一個公共父類中以避免代碼重複。這是Opdyke和Johnson所描述過的“重分解以一般化”的一個很好的例子。首先識別現有代碼中的不同之處,並且將不同之處分離爲新的操作。最後,用一個調用這些新的操作的模板方法來替換這些不同的代碼。
-
控制子類擴展。模板方法只在特定點調用“hook”操作,這樣就只允許在這些點進行擴展。
訪問者模式(Visitor)
意圖
訪問者模式
表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
適用性
-
一個對象結構包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴於其具體類的操作。
-
需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“污染”這些對象的類。Visitor使得你可以將相關的操作集中起來定義在一個類中。當該對象結構被很多應用共享時,用Visitor模式讓每個應用僅包含需要用到的操作。
-
定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的接口,這可能需要很大的代價。如果對象結構類經常改變,那麼可能還是在這些類中定義這些操作較好。