基礎筆記(二):設計模式摘錄

基礎筆記(二):設計模式摘錄

 

前言

       收錄一些自己在開發過程中比較常用的模式,整理出來以便自己複習,畢竟熟才能生巧,才能變通,舉一反三。
設計模式在大多數靈活性好、可擴展性高、可移植的優秀程序中都有運用,比如界面展現層運用的MVC模式的主要關係就是由Observer(View-Model)、Composite(CompositeView嵌套視圖)和Strategy(View-Controller)三個設計模式給出的。下面只列出模式的脈絡大綱,如果想再拓展開且有時間的可以把經典磚頭《設計模式》多嚼幾遍。如果想了解個入門的,也可以看下《大話設計模式》。
 

目錄

圖示符號說明

生成器(Builder)

模板方法(Template Method)

觀察者模式(Observer)

中介者(Mediator)

單件(Singleton)

工廠方法(Factory Method)

抽象工廠(Abstract Factory)

組成(Composite)

裝飾(Decorator)

橋接(Bridge)

迭代器(Iterator)

 

 

一 、圖示符號說明

1.類圖
  • 抽象類和具體類

  • 參與者客戶類(左)和絕對客戶類(右)

  • 類關係

  • 僞代碼註解

2.對象圖
 
 
 

二、生成器(Builder)

將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
結構
參與者
  • Builder

爲創建一個Product對象的各個部件指定抽象接口。

  • ConcreteBuilder

實現Builder的接口以構造和裝配該產品的各個部件。

定義並明確它所創建的表示。

提供一個檢索產品的接口。

  • Director

構造一個使用Builder接口的對象。

  • Product

表示被構造的複雜對象。ConcreteBuilder創建該產品的內部表示並定義它的裝配過程。

包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。

 協作

  • 客戶創建Director對象,並用它想要的Builder對象進行配置。
  • 一旦產品部件被生成,導向器就會通知生成器。
  • 生成器處理導向器的請求,並將部件添加到該產品中。
  • 客戶從生成器中檢索產品。

效果
  1. 它使你可以改變一個產品的內部表示:Builder對象嚮導向器提供一個構建產品的抽象接口。
  2. 它將構建代碼和表示代碼分開:每個子Builder包含了創建和裝配一個特定產品的所有代碼,然後不同的Director可以複用它以在相同部件集合的基礎上構作不同的Product。
  3. 它使你可對構造過程進行更精細的控制:僅當產品完成時導向器才能從生成器中取回它。
實現
  1. 裝配和構造接口
  2. 產品沒有抽象類
  3. 在Builder缺省的方法爲空
Builder模式和Abstract Factory 相似,主要區別在於Builder模式着重於一步步構建一個複雜對象,在最後一步返回產品,而Abstract Factory着重於多個系列的產品對象,產品是立即返回的。
 
 
 

三、模板方法(Template Method)

定義一個操作中算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
(模板方法:在方法體中一次性實現一個算法的不變部分,將可變的行爲留給子類實現。)
結構
參與者
  • AbstractClass

定義抽象的原語操作(primitive operation),具體的子類將重定義它們以實現一個算法的各步驟。

實現一個模板方法,定義一個算法的骨架。該模板方法不僅調用原語操作,也調用定義在AbstractClass或其他對象中的操作。

  • ConcreteClass

實現原語操作以完成算法中與特定子類相關的步驟。

協作

ConcreteClass靠AbstractClass來實現算法中不變的步驟。
 
效果
模板方法應該指明那些操作是鉤子操作(可以被重定義)以及哪些是抽象操作(必須被重定義),子類編寫者必須明確瞭解哪些操作是設計爲有待重定義的。

 
相關模式
Factory Method:在子類現象的函數中經常調用Factory Method。
模板方法使用繼承來改變算法的一部分,Strategy使用委託來改變整個算法。
 
 

四、觀察者模式(Observer)

定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都會得到通知並被自動更新。
結構
參與者
  • Subject(目標)

目標知道它的觀察者。可以有任意多個觀察者觀察同一個目標。

提供註冊和刪除觀察者對象的接口。
  • Observer(觀察者)

爲那些在目標發生改變時需獲得通知的對象定義一個更新接口。

  • ConcreteSubject(具體目標)

將有關狀態存入各ConcreteObserver對象。

當它的狀態發生改變時,向它的各個觀察者發出通知。

  • ConcreteObserver(具體觀察者)

維護一個指向ConcreteSubject對象的引用。

存儲有關狀態,這些狀態應與目標的狀態保持一致。

實現Observer的更新接口以使自身狀態與目標的狀態保持一致。

協作
優缺點
  1. 目標和觀察者間的抽象耦合;
  2. 支持廣播通信
  3. 意外的更新
實現
  1. 創建目標到觀察者之間的映射:當目標很多而觀察者較少時,可以用hash表做映射關聯。
  2. 觀察多個目標:一個觀察者依賴於多個目標時,目標對象可以將自己作爲Update()操作的一個參數,讓觀察者知道應該去檢查哪一個目標。多次連續操作效率低。
  3. 誰觸發更新:一 在目標對象的SetState()(狀態設定操作)中改變目標對象狀態後自動調用Notify;二 讓客戶自己一系列操作更改完後在目標對象上調用Notify。客戶可能會忘記調用,容易出錯。
  4. 在觀察者中避免對已刪除目標的懸掛引用。當一個目標被刪除時,讓它通知它的觀察者將該目標的引用復位。
  5. 在發出通知前確保目標的狀態自身是一致的。
  6. 避免特定於觀察者的更新協議——推/拉模型
  7. 顯示地指定感興趣的改變(Aspect& interest)
  8. 封裝複雜的更新語義(更改管理器ChangeManager)

           ChangeManager充當目標和觀察者之間的中介者(Mediator模式),可使用Singleton模式來保證它是唯一的並且是可全局訪問的。

 

     9.  結合目標類和觀察者類(在不支持多重繼承的語言中使用)
 
 

五、中介者(Mediator)

用一箇中介對象來封裝一系列的對象交互。中介者使各對象不需要顯示地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
(中介者充當一箇中介以使組中的對象不再相互顯示引用。這些對象僅知道中介者,從而減少了相互連接的數目。)
結構
參與者
  • Mediator(中介者)

中介者定義一個接口用於與各同事(Colleague)對象通信。

  • ConcreteMediator(具體中介者)

具體中介者通過協調各同事對象實現協作行爲。

瞭解並維護它的各個同事。

  • Colleague class(同事類)

每一個同事類都知道它的中介者對象。

每一個同事對象在需與其他的同事通信的時候,與它的中介者通信。

 

協作
同事向一箇中介者對象發送和接收請求。中介者在各同事間適當地轉發請求以實現協作行爲。
 
相關模式
Colleague可使用Observer模式與Mediator通信。
 
 
 

六、單件(Singleton)

保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
結構
參與者
  • Singleton

定義一個Instance操作,允許客戶訪問它的唯一實例。Instance是一個類操作。

可能負責創建它自己的唯一實例。

協作
客戶只能通過Singleton的Instance操作訪問一個Singleton的實例。
優點
  1. 對唯一實例的受控訪問
  2. 縮小名空間,避免那些存儲唯一實例的全局變量污染名空間
  3. 允許對操作和表示的精化:Singleton類可以有子類。
  4. 允許可變數目的實例:這個模式使得你易於改變你的想法,並允許Singleton類有多個實例。此外,你可以用相同的方法來控制應用所使用的實例數目。
  5. 比類操作更靈活
    (惰性初始化:它的返回值直到被第一次訪問時才創建和保存)
實現
保證一個唯一的實例:常用的方法是將創建這個實例的操作隱藏在一個類操作,如通過靜態成員函數作爲全局訪問點公佈出去。
創建Singleton類的子類:指向單件實例的變量必須用子類的實例初始化,方法有三種
  1. 在Singleton的Instance操作中決定你要使用的是哪一個單件。
  2. 將Instance的實現從父類中分離出來在子類中實現。
  3. 使用一個靜態的單件註冊表,根據名字,單件實例鍵值對進行存儲,在子類中註冊供。比前面兩種靈活。
 
 

七、工廠方法(Factory Method)

定義一個用於創建對象的接口,讓子類決定將哪一個類實例化,Factory Method使一個類的實例化延遲到其子類。
結構
參與者
  • Product

定義工廠方法所創建的對象的接口。

  • ConcreteProduct

實現Product接口。

  • Creator

聲明工廠方法,該方法返回一個Product類型的對象。Creator也可以定義一個工廠方法的缺省實現,它返回一個缺省的ConcreteProduct對象。

可以調用工廠方法以創建一個Product對象。

  • ConcreteCreator

重定義工廠方法以返回一個ConcreteProduct實例。

協作
Creator依賴於它的子類來定義工廠方法,以返回一個適當的ConcreteProduct實例。
 
相關模式
  1. Abstract Factory經常用工廠方法來實現(抽象工廠中的工廠可以理解爲工廠方法,相當於集合多個工廠方法);
  2. 工廠方法通常在Template Methods模式中被調用(一個方法可以同時是工廠方法和模板方法);
 
 

八、抽象工廠(Abstract Factory)

提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
客戶僅與抽象類定義的接口交互,而不使用特定的具體類的接口
結構
參與者
  • AbstractFactory

聲明一個創建抽象產品對象的操作接口。

  • ConcreteFactory

實現創建具體產品對象的操作。

  • AbstractProduct

爲一類產品對象聲明一個接口。

  • ConcreteProduct

定義一個將被相應的具體工廠創建的產品對象。

實現AbstractProduct接口。

  • Client

僅使用由AbstractFactory和AbstractProduct類聲明的接口。

協作
通常在運行時刻創建一個ConcreteFactory類的實例。這一具體的工廠創建具有特定實現的產品對象。爲創建不同的產品對象。客戶應使用不同的具體工廠。
Abstract Factory將產品對象的創建延遲到它的ConcreteFactory子類。
優缺點
  1. 它分離了具體的類:客戶通過工廠和產品的抽象接口操縱它們的實例。
  2. 它使得易於交換產品系列:一個具體工廠類在一個應用中僅出現一次,即在它初始化的時候,這使得改變一個應用的具體工廠變得容易。
  3. 它有利於產品的一致性:當一個系列的產品對象被設計在一起工作時,一個應用一次只能使用同一系列的產品對象。
  4. 難以支持新種類的產品:支持新產品就需要擴展工廠接口,這將涉及Abstract Factory類和所有子類的改變。解決方案:
實現
  1. 將工作作爲單件:一個應用中一般只需一個具體工廠(產品系列)
  2. 創建產品:使用工廠方法(Factory Method)實現。多個產品系列時可以考慮使用原型模式(Prototype),具體工廠使用產品系列中每一個產品的原型實例來初始化,且它通過複製它的原型來創建新的產品。在基於原型的方法中,使得不是每個新的產品系列都需要一個新的具體工廠類。
 

 

九、組成(Composite)

將對象組合成樹形結構以表示“部分-整體”的層次關係。Composite使得用戶對單個對象和組合對象的使用具有一致性。
結構
參與者
  • Component

爲組合中的對象聲明接口。

在適當的情況下,實現所有類共有接口的缺省行爲。

聲明一個接口用於訪問和管理Component的子組件。

(可選)在遞歸結構中定義一個接口,用於訪問一個父部件,並在合適的情況下實現它。

  • Leaf

在組合中表示葉節點對象,葉節點沒有子節點。

在組合中定義圖元對象的行爲。

  • Composite

定義有子部件的那些部件的行爲。

存儲子部件。

在Component接口中實現與子部件有關的操作。

  • Client

通過Component接口操縱組合部件的對象。

協作
用戶使用Component類接口與組合結構中的對象進行交互。如果接收者是一個葉節點,則直接處理請求。如果接收者是Composite,它通常將請求發給它的子部件,在轉發請求之前或之後可能執行一些輔助操作。
 
實現
  1. 顯式的父部件引用,同時父部件引用也應支持Chain of Responsibility模式。
  2. 共享組件:與Flyweight模式共同使用。
  3. 最大化Component接口:Component類儘可能涵蓋Leaf和Composite類的公共操作。
  4. 聲明管理子部件的操作:在透明性和安全性中作權衡,說明如上圖。
  5. 在基類Component中實現一個Component列表:只有當該結構中子類的數目相對較少時,才值得使用這種方法。否則對葉節點來說會導致空間浪費。
  6. 子部件排序:可使用terator模式。
  7. 使用高速緩衝存貯改善性能:緩衝存儲常用信息。
  8. 應該由誰刪除Component:最好由Composite類負責刪除其子節點。但有一種情況除外,即Leaf對象不會改變,因此可以被共享。
  9. 存貯組件組好用哪一種數據結構
相關模式
子部件-父部件連接用Chain of Responsibility模式
Composite模式經常和Decorator模式一起使用
Flyweight讓你共享組件,但不再能引用他們的父部件
Itertor可用來遍歷Composite
Visitor將本來應該分佈在Composite和Leaf類中的操作和行爲局部化
 

十、裝飾(Decorator)

動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類方式更爲靈活。
結構
參與者
  • Component

定義一個對象接口,可以給這些對象動態地添加職責。

  • ConcreteComponent

定義一個對象,可以給這個對象添加一些職責。

  • Decorator

維持一個指向Component對象的指針,並定義一個與Component接口一致的接口。

  • ConcreteDecorator

向組件添加職責。

協作
Decorator將請求轉發給它的Component對象,並有可能在轉發請求前後執行一些附加的動作。
 
優缺點
  1. 比靜態繼承更靈活:可以在運行時增加和刪除裝飾。
  2. 避免在層次結構高層的類有太多的特徵:通過從簡單的部件開始,逐步組合出複雜的功能。
  3. Decorator和它的Component不一樣:一個被裝飾的組件和這個組件是有差別的,因此不能採用對象標識去作爲判斷的依據(不依賴對象標識)。
  4. 有許多小對象
實現
  1. 接口的一致性:裝飾對象的接口必須與它所裝飾的Component的接口是一致的。
  2. 省略抽象的Decorator類:當僅需要添加一個職責時,可以把Decorator向Component轉發請求的職責合併到唯一的ConcreteDecorator中。
  3. 保持Component類的簡單性
  4. 改變對象的外殼(採用Decorator模式)與改變對象的內核(採用Strategy模式)

 

採用Decorator模式

 

 

採用Strategy模式

 

 

 
 

 

十一、橋接(Bridge)

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

結構
參與者
  • Abstraction

定義抽象類的接口。

維護一個指向Implementor類型對象的指針。

  • RefinedAbstraction

擴充由Abstraction定義的接口。

  • Implementor

定義實現類的接口,該接口不一定要與Abstraction的接口完全一致;事實上這兩個接口可以完全不同。一般來講,Impementor接口僅提供基本操作,而Abstraction則定義了基於這些基本操作的較高層次的操作。

  • ConcreteImplementor

實現Implementor接口並定義它的具體實現。

 

協作

Abstraction將Client的請求轉發給它的Implementor對象。

 

優點

分離接口及其實現部分

提高可擴充性

實現細節對客戶透明

 

 

 

十二、迭代器(Iterator)

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

結構

參與者

  • Iterator(迭代器)

迭代器定義訪問和遍歷元素的接口。

  • ConcreteIterator(具體迭代器)

具體迭代器實現迭代器接口。

對該聚合遍歷時跟蹤當前位置。

  • Aggregate(聚合)

聚合定義創建相應迭代器對象的接口。

  • ConcreteAggregate(具體聚合)

具體聚合實現創建相應迭代器的接口,該操作返回ConcreteIterator的一個適當的實例。

 

 

協作

ConcreteIterator跟蹤聚合中的當前對象,並能計算出待遍歷的後續對象。

效果

它支持以不同的方式遍歷一個聚合:複雜的聚合可以使用多種方式進行遍歷。

迭代器簡化了聚合的接口:有了迭代器的遍歷接口,聚合本身就不再需要類似的遍歷接口了。

在同一個聚合上可以同時有多個遍歷

實現

誰控制該迭代:當使用該迭代器的客戶來控制迭代時,該迭代器稱爲一個外部迭代器(推薦)。而當由迭代器控制迭代時,該迭代器稱爲一個內部迭代器。

外部迭代器:var aIterator=aList.CreateIterator(); 

                     for(altertor.First();altertor.IsDone();altertor.Next()){…..}

 

內部迭代器:var aTraverser=new Traverser(aList); //aTraverser內部已經包含了aIterator,在aTraverser內部對aList進行遍歷

                     aTraverser.Traverse();

 

誰定義遍歷算法:由迭代器負責(推薦),或由聚合本身負責,然後用迭代器(這時可稱爲遊標)來存儲當前迭代的狀態,指示當前位置。

附加的迭代器操作:迭代器的最小接口由First、Next、IsDone和CurrentItem操作組成。

相關模式

 

Composite:迭代器常被應用到像複合這樣的遞歸結構上。

FactoryMethod:多態迭代器靠Factory Method來實例化適當的迭代器子類。

Memento:常與迭代器模式一起使用。迭代器可使用一個memento來捕獲一個迭代的狀態。迭代器在其內部存儲memento。

 

 

相關資料:

  • 《設計模式》
  • 《大話設計模式》
  • **基礎筆記(二):設計模式摘錄**

 

作者:B.it
出處:http://www.cnblogs.com/ImBit/p/5492260.html                                           
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章