學習:設計模式 可複用面向對象軟件的基礎 【引言】

1.1什麼是設計模式

問題一:什麼是設計模式?

提供相關問題的解決方案

問題二:一個模式的基本要素是什麼?

模式名稱(pattern name)

問題(problem)

解決方案(solution)

效果(consequences)

1.2smalltalk MVC中的設計模式

類的模型/視圖/控制器(Model/view/controller)

模型Model是應用對象,視圖View是它在屏幕上的標示,控制器Controller定義用戶界面對用戶輸入的響應方式。不使用MVC,用戶界面設計往往將這些對象混在一起,而MVC則將他們分離以提高靈活性和複用性。

MVC通過建立一個“訂購/通知”協議來分離視圖和模型。視圖必須保證它的顯示正確地反映了模型的狀態。一旦模型的數據發生變化,模型將通知有關的視圖,每個視圖相應地得到刷新自己的機會。這種方法可以讓你爲一個模型提供不同的多個視圖表現形式,也能夠爲一個模型創建新的視圖而無須重寫模型。

MVC的主要關係是由Observer,Composite和Strategy三個設計模式給出的

Observer    反映了將視圖和模型分離的設計,然而這個而設計還可用於解決更一般的問題:將對象分離,使得一個對象的改變能夠影響另一些對象,而這個對象並不需要知道那些被影響的對象的細節。

Composite    MVC的另一個特徵是視圖可以嵌套。例如,按鈕控制面板可以用一個嵌套了按鈕的複雜視圖來實現。對象查看器的用戶界面可由嵌套的視圖構成,這些視圖又可複用於調試器。MVC用View類的子類——CompositeView類來支持嵌套視圖。CompositeView類的對象行爲上類似於View類的對象,一個組合視圖可用於任何視圖可用的地方,但是它包含並管理嵌套視圖。這個例子反映了可以將組合視圖與其構件平等對待的設計,同樣地,改設計也適用於更一般的問題:將一些對象劃爲一組,並將該組對象當作一個對象來使用。這個設計被描述爲Composite模式,該模式允許你創建一個類層次結構,一些子類定義了原子對象(如Button)而其他類定義了組合對象(CompositeView),這些組合對象是由原子對象組合而成的更復雜的對象。

Strategy      MVC允許你在不改變視圖外觀的情況下改變視圖對用戶輸入的響應方式。例如:你可能希望改變視圖對鍵盤的響應方式,或希望使用彈出式菜單而不是原來的命令鍵方式。MVC將響應機制封裝在Controller對象中。存在着一個Controller的類層次結構,使得可以方便地對原有Controller做適當改變而創建新的Controller。View使用Controller子類的實例來實現一個特定的響應策略。要實現不同的響應策略只要用不同種類的Controller實例替換即可。甚至可以在運行時刻通過改變View的Controller來改變View對用戶輸入的響應方式。例如,一個View可以被禁止接收任何輸入,只需要給它一個忽略輸入事件的Controller。View-Controller關係是Strategy模式的一個例子。一個策略是一個表述算法的對象。當你想靜態或動態替換一個算法,或你有很多不同的算法,或算法中包含你想封裝的複雜數據結構,這時策略模式是非常有用的。

1.3描述設計模式

爲了達到設計複用,我們必須同時記錄設計產生的決定過程,選擇過程和權衡過程。具體的例子也是很重要的,它們讓你看到實際的設計。

設計模式的模板組成成分

模式名和分類

意圖

(是回答下列問題的簡單稱述:設計模式是做什麼的?它的基本原理和意圖是什麼?它解決的是什麼樣的特定設計問題?)

別名

動機

(用以說明一個設計問題以如何用模式中得類,對象來解決該問題的特定情景。該情景會幫助你理解隨後對模式更抽象的描述。)

適用性

(什麼情況下可以使用該設計模式?該模式可用來改進哪些不良設計?你怎樣識別這些情況?)

結構

(採用基於對象建模技術的表示法對模式中的類進行圖形描述。)

參與者

(指設計模式中的類和/或對象以及它們各自的職責。)

協作

(模式的參與者怎樣協作以實現它們的職責。)

效果

(模式怎樣支持它的目標?使用模式的效果和所需做的權衡取捨?系統結構的哪些方面可以獨立改變?

實現

(實現模式時需要知道的一些提示,技術要點及應避免的缺陷,以及是否存在某些特定於實現語言的問題。

代碼示例

已知應用

相關模式

(與這個模式緊密相關的模式有哪些?其間重要的不同之處是什麼?這個模式應與哪些其他模式一起使用?)

1.4設計模式的編目

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

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

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

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

Chain of Responsibility:爲解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它。

Command:將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作。

Composite:將對象組合成樹形結構以表示“部分——整體”的層次結構。Composite使得客戶對單個對象和複合對象的使用具有一致性。

Decorator:動態地給一個對象添加一些額外的職責。就擴展功能而言,Decorator模式比生成子類方式更爲靈活。

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

Factory Method:定義一個用於創建對象的接口,讓子類決定將哪一個類實例化。Factory Method使一個類的實例化延遲到其子類。

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

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

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

Mediator:用一箇中介對象來封裝一系列的對象交互。終結者使各對象不需要顯式地相互引用,從而使耦合鬆散,而且可以獨立地改變他們之間的交互。

Memento:在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。

Observer:定義對象間的一種一對多的依賴關係,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動刷新。

Prototype:用原型實例指定創建對象的種類,並且通過拷貝這個原型來創建新的對象。

Proxy:爲其他對象提供一個代理以控制對這個對象的訪問。

Singleton:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

State:允許一個對象在其內部狀態改變時改變它的行爲。對象看起來似乎修改了它所屬的類。

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

Template Method:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

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

於這些元素的新操作。

1.5組織編目

我們根據兩條準則對模式進行分類。第一是目的準則,即模式是用來完成什麼工作的。模式依據其目的可分爲

創建型(Creational),結構型(Structural),或行爲型(Behavioral)三種。創建型模式與對象的創建有

關;結構型模式處理類或對象的組合;行爲型模式對類或對象怎樣交互和怎樣分配職責進行描述。

第二是範圍準則,指定模式主要是用於類還是用於對象。類模式處理類和子類之間的關係,這些關係通過集成

建立,是靜態的,在編譯時刻便確定下來了。對象模式處理對象間的關係,這些關係在運行時刻是可以變化的

,更具動態性。從某種意義上來說,幾乎所有模式都是用繼承機制,所以“類模式”只指那些集中於處理類間

關係的模式,而大部分模式都屬於對象模式的範疇。

創建型類模式將對象的部分創建工作延遲到子類,而創建型對象模式則將它延遲到另一個對象中。結構型類模

式使用繼承機制來組合類,而結構型對象模式則描述了對象的組裝方式。行爲型類模式使用繼承描述算法和控

制流,而行爲型對象模式則描述一組對象怎樣協作完成單個對象所無法完成的任務。

 1.6 設計模式怎樣解決設計問題

1.6.1 尋找合適的對象

客戶請求是使對象執行操作的唯一方法,操作又是對象改變內部數據的唯一方法。由於
這些限制,對象的內部狀態是被封裝的,它不能被直接訪問,它的表示對於對象外部是不可
見的。
面向對象設計最困難的部分是將系統分解成對象集合。因爲要考慮許多因素:封裝、粒
度、依賴關係、靈活性、性能、演化、複用等等,它們都影響着系統的分解,並且這些因素
通常還是互相沖突的。

設計模式幫你確定並不明顯的抽象和描述這些抽象的對象。例如,描述過程或算法的對
象現實中並不存在,但它們卻是設計的關鍵部分。S t r a t e g y ( 5 . 9 )模式描述了怎樣實現可互換的
算法族。S t a t e ( 5 . 8 )模式將實體的每一個狀態描述爲一個對象。這些對象在分析階段,甚至在
設計階段的早期都並不存在,後來爲使設計更靈活、複用性更好纔將它們發掘出來。

1.6.2 決定對象的粒度

F a c a d e ( 4 . 5 )模式描述了怎樣用對象表示完整的子系統,
F l y w e i g h t ( 4 . 6 )模式描述瞭如何支持大量的最小粒度的對象。其他一些設計模式描述了將一個
對象分解成許多小對象的特定方法。Abstract Factory(3.1)和B u i l d e r ( 3 . 2 )產生那些專門負責生
成其他對象的對象。Vi s i t o r ( 5 . 1 0 )和C o m m a n d ( 5 . 2 )生成的對象專門負責實現對其他對象或對象
組的請求。

1.6.3 指定對象接口

對象聲明的每一個操作指定操作名、作爲參數的對象和返回值,這就是所謂的操作的型
構( s i g n a t u r e )。對象操作所定義的所有操作型構的集合被稱爲該對象的接口( i n t e r f a c e )。對象
接口描述了該對象所能接受的全部請求的集合,任何匹配對象接口中型構的請求都可以發送
給該對象。

類型(type) 是用來標識特定接口的一個名字。如果一個對象接受“ Wi n d o w”接口所定義
的所有操作請求,那麼我們就說該對象具有“ Wi n d o w”類型。一個對象可以有許多類型,並
且不同的對象可以共享同一個類型。對象接口的某部分可以用某個類型來刻畫,而其他部分
則可用其他類型刻畫。兩個類型相同的對象只需要共享它們的部分接口。接口可以包含其他
接口作爲子集。當一個類型的接口包含另一個類型的接口時,我們就說它是另一個類型的子
類型( s u b t y p e ),另一個類型稱之爲它的超類型( s u p e r t y p e )。我們常說子類型繼承了它的超類型
的接口。

在面向對象系統中,接口是基本的組成部分。對象只有通過它們的接口才能與外部交流,
如果不通過對象的接口就無法知道對象的任何事情,也無法請求對象做任何事情。對象接口
與其功能實現是分離的,不同對象可以對請求做不同的實現,也就是說,兩個有相同接口的
對象可以有完全不同的實現。

設計模式通過確定接口的主要組成成分及經接口發送的數據類型,來幫助你定義接口。
設計模式也許還會告訴你接口中不應包括哪些東西。

設計模式也指定了接口之間的關係。特別地,它們經常要求一些類具有相似的接口;或
它們對一些類的接口做了限制。

1.6.4 描述對象的實現

抽象類(abstract class)的主要目的是爲它的子類定義公共接口。一個抽象類將把它的部分
或全部操作的實現延遲到子類中,因此,一個抽象類不能被實例化。在抽象類中定義卻沒有
實現的操作被稱爲抽象操作(abstract operation)。非抽象類稱爲具體類(concrete class)。
子類能夠改進和重新定義它們父類的操作。更具體地說,類能夠重定義( o v e r r i d e )父類定
義的操作,重定義使得子類能接管父類對請求的處理操作。類繼承允許你只需簡單的擴展其
他類就可以定義新類,從而可以很容易地定義具有相近功能的對象族。

1. 類繼承與接口繼承的比較
理解對象的類( c l a s s )與對象的類型( t y p e )之間的差別非常重要。

一個對象的類定義了對象是怎樣實現的,同時也定義了對象的內部狀態和操作的實現。
但是對象的類型只與它的接口有關,接口即對象能響應的請求的集合。一個對象可以有多個類型,不同類的對象可以有相同的類型。

當然,對象的類和類型是有緊密關係的。因爲類定義了對象所能執行的操作,也定義了
對象的類型。當我們說一個對象是一個類的實例時,即指該對象支持類所定義的接口。

理解類繼承和接口繼承(或子類型化)之間的差別也十分重要。類繼承根據一個對象的實現
定義了另一個對象的實現。簡而言之,它是代碼和表示的共享機制。然而,接口繼承(或子類
型化)描述了一個對象什麼時候能被用來替代另一個對象。

儘管大部分程序設計語言並不區分接口繼承和實現繼承的差別,但使用中人們還是分別
對待它們的。S m a l l t a l k程序員通常將子類當作子類型(儘管有一些熟知的例外情況[ C o o 9 2 ] ),
C + +程序員通過抽象類所定義的類型來操縱對象。
很多設計模式依賴於這種差別。例如, Chain of Responsibility(5.1)模式中的對象必須有一
個公共的類型,但一般情況下它們不具有公共的實現。在C o m p o s i t e ( 4 . 3 )模式中,構件定義了
一個公共的接口,但C o m p o s i t e通常定義一個公共的實現。C o m m a n d ( 5 . 2 )、O b s e r v e r ( 5 . 7 )、
S t a t e ( 5 . 8 )和S t r a t e g y ( 5 . 9 )通常純粹作爲接口的抽象類來實現。

2. 對接口編程,而不是對實現編程

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