目錄
設計模式分類
模式的目的 (Purpose),即模式是用來完成什么工作的:
- 創建型 (Creational) 模式與對象的創建有關;
- 結構型 (Structural) 模式處理類或對象的組合;
- 行為型 (Behavioral) 模式對類或對象怎樣交互和怎樣分配職責進行描述;
模式的范圍 (Scope),即模式主要用于類還是用于對象。
- 類模式 (Class),處理類和子類之間的關系,這些關系通過繼承建立,在編譯時即確定,具有靜態性;
- 對象模式 (Object),處理對象間的關系,這些關系在運行時是可變化的,具有動態性;
創建型類模式將對象的部分創建工作延遲到子類;
創建型對象模式將對象的部分創建工作延遲到另一個對象中;
結構型類模式使用繼承機制類組合類;
結構型對象模式描述了對象的組裝方式;
行為型類模式使用繼承描述算法和控制流;
行為型對象模式描述一組對象怎樣寫作完成單個對象無法完成的任務;
設計模式之間的關系
設計模式所支持的設計的可變方面
設計模式怎樣解決設計問題
尋找合適的對象
面向對象程序由對象組成,對象包括數據和對數據進行操作的過程,過程通常稱為方法或操作。
對象在收到客戶的請求(或消息)后,執行相應的操作。
客戶請求是使對象執行操作的唯一方法,操作又是對象改變內部數據的唯一方法。
由于這些限制,對象的內部狀態是被封裝的,它不能被直接訪問,它的表示對于對象外部是不可見的。
面向對象設計最困難的部分是將系統分解成對象集合。
因為要考慮許多因素:封裝、粒度、依賴關系、靈活性、性能、演化、復用等,它們都影響著系統的分解,并且這些因素通常還是互相沖突的。
設計的許多對象來源于現實世界的分析模型。但是,設計結果所得到的類通常在現實世界中并不存在,有些是像數組之類的低層類,而另一些則層次較高。
設計模式幫你確定并不明顯的抽象和描述這些抽象的對象。例如,描述過程或算法的對象現實中并不存在,但它們卻是設計的關鍵部分。
決定對象的粒度
對象在大小和數目上的變化極大。它們能表示下自硬件或上自整個應用的任何事物。
那么我們怎么決定一個對象應該是什么呢?設計模式很好地講述了這個問題。
Facade 模式描述了怎樣用對象表示完整的子系統。
Flyweight 模式描述了如何支持大量的最小粒度的對象。
其他一些設計模式描述了將一個對象分解成許多小對象的特定方法。
Abstract Factory 和 Builder 模式產生那些專門負責生成其他對象的對象。
Visitor 和 Command 生成的對象專門負責實現對其他對象或對象組的請求。
指定對象接口
對象聲明的每一個操作指定操作名、作為參數的對象和返回值,這就是所謂的操作的型構(Signature)。
對象操作所定義的所有操作型構的集合被稱為該對象的接口(Interface)。
對象接口描述了該對象所能接受的全部請求的集合,任何匹配對象接口中型構的請求都可以發送給該對象。
設計模式通過確定接口的主要組成成分及經接口發送的數據類型,來幫助你定義接口。
設計模式指定了接口之間的關系。它們經常要求一些類具有相似的接口,或它們對一些類的接口做了限制。
類型(Type)是用來標識特定接口的一個名字。
當一個類型的接口包含另一個類型的接口時,我們就說它是另一個類型的子類型(Subtype),另一個類型稱之為它的超類型(Supertype)。
我們常說子類型繼承了它的超類型的接口。
在面向對象系統中,接口時基本的組成部分。對象只有通過它們的接口才能與外部交流。
對象接口與其功能實現是分離的,不同對象可以對請求做不同的實現。
多態(Polymorphism)
當給對象發送請求時,所引起的具體操作既與請求本身有關又與接受對象有關。
支持相同請求的不同對象可能對請求激發的操作有不同的實現。
發送給對象的請求和它的相應操作在運行時刻的連接就稱之為動態綁定(Dynamic Binding)。
動態綁定是指發送的請求知道運行時刻才受你的具體的實現的約束。
動態綁定允許你在運行時刻彼此替換有相同接口的對象。這種可替換性就稱為多態(Polymorphism)。
多態允許客戶對象僅要求其他對象支持特定的接口,除此之外對其假設幾近于無。
描述對象的實現
對象通過實例化類來創建,此對象被稱為該類的實例。
抽象類(Abstract Class)的主要目的是為它的子類定義公共接口。
一個抽象類將把它的部分或全部操作的實現延遲到子類中,因此,一個抽象類不能被實例化。
子類能夠重定義(override)父類定義的操作,重定義使得子類能接管父類對請求的處理操作。
類繼承允許你只需簡單的擴展其他類就可以定義新類,從而可以很容易地定義具有相近功能的對象族。
類繼承根據一個對象的實現定義了另一個對象的實現。簡而言之,它是代碼和表示的共享機制。
接口繼承(或子類型化)描述了一個對象什么時候能被用來替代另一個對象。
盡管大部分程序設計語言并不區分類繼承和接口繼承,但使用中人們還是分別對待它們的。
面向對象的設計原則:針對接口編程,而不是針對實現編程。
運用復用機制
面向對象系統中功能復用的兩種最常用技術室類繼承和對象組合(Object Composition)。
類繼承允許你根據其他類的實現來定義一個類的實現。這種通過生成子類的復用通常被稱為白箱復用(White-Box Reuse)。
新的更復雜的功能可以通過組裝或組合對象來獲得。這種復用風格被稱為黑箱復用(Black-Box Reuse)。因為對象的內部細節是不可見的。
父類通常至少定義了部分子類的具體表示。因此繼承對子類揭示了其父類的實現細節,所以繼承常被認為“破壞了封裝性”。
一個可用的解決方法就是只繼承抽象類,因為抽象類通常提供較少的實現。
對象組合是通過獲得對其他對象的引用而在運行時刻動態定義的。組合要求對象遵守彼此的接口約定,進而要求更仔細地定義接口。
因為對象只能通過接口訪問,所以我們并不破壞封裝性。
使用對象組合有助于保持每個類被封裝并被集中在單個任務上,這樣類和類繼承層次會保持較小規模。
面向對象的設計原則:優先使用對象組合,而不是類繼承。
關聯運行時和編譯時的結構
代碼不可能揭示關于系統如何工作的全部,系統的運行時結構更多地受到設計者的影響,而不是編程語言。
對象和它們的類型之間的關系必須更加仔細的設計,因為它們決定了運行時程序結構的好壞。
許多設計模式顯式地記述了編譯時和運行時結構的差別。
Composite 和 Decorator 對于構造復雜的運行時結構特別有用。
Observer 也與運行時結構有關。
Chain of Responsibility 也產生了繼承所無法展現的通信模式。
設計應支持變化
獲得最大限度復用的關鍵在于對新需求和已有需求發生變化時的預見性,要求你的系統設計要能夠相應的改進。
一個不考慮系統變化的設計在將來就有可能需要重新設計。
設計模式可以確保系統能以特定方式變化,從而幫助你避免重新設計系統。
源代碼
以上內容全部來自《Design Patterns: Elements of Reusable Object-Oriented Software》一書。
文章列表