2006.10.23 李建忠
建立型模式
Singleton模式解決的是實體物件個數的問題。除了Singleton之外,其他建立型模式解決的都是new所帶來的耦合關係。
Factory Method,Abstract Factory,Builder都需要一個額外的工廠類來負責執行個體化“易變對象”,而Prototype則是通過原型(一個特殊的工廠類)來複製“易變對象”。
如果遇到“易變類”,起初的設計通常從Factory Method開始,當遇到更多的複雜變化時,再考慮重構為其他三種原廠模式(Abstract Factory,Builder,Prototype)。
結構型模式
Adapter模式注重轉換介面,將不吻合的介面適配對接(適合於舊系統)
Bridge模式注重分離介面與其實現,支援多維度變化
Composite模式注重統一介面,將“一對多”的關係轉化為“一對一”的關係
Decorator模式注重穩定介面,在此前提下為對象擴充功能
Facade模式注重簡化介面,簡化組件系統與外部客戶程式的依賴關係
Flyweight模式注重保留介面,在內部使用共用技術對Object Storage Service進行最佳化
Proxy模式注重假借介面,增加間接層來實現靈活控制
行為型模式
Template Method模式封裝演算法結構,支援演算法子步驟變化
Strategy模式注重封裝演算法,支援演算法的變化
State模式注重封裝與狀態相關的行為,支援狀態的變化
Memento模式注重封裝對象狀態變化,支援狀態儲存/恢複
Mediator模式注重封裝對象間的互動,支援對象互動的變化
Chain Of Responsibility模式注重封裝對象責任,支援責任的變化
Command模式注重將請求封裝為對象,支援要求的變化
Iterator模式注重封裝集合對象內部結構,支援集合的變化
Interpreter模式注重封裝特定領域變化,支援領域問題的頻繁變化
Observer模式注重封裝對象通知,支援通訊對象的變化
Visitor模式注重封裝對象操作變化,支援在運行時為類階層動態添加新的操作
模式之間的關係圖
例說模式綜合應用
我們以做一個檔案分割器為例
剛開始做的時候我們並不知道應該用什麼模式。
瀏覽
分割,把檔案作二進位處理,拿到檔案長度,和分割數量,然後順序讀取檔案進行處理。
從設計層面來想,這樣的設計是很粗糙的。能正常工作並不意味著能很好的工作。
假如現在提出幾個需求:
1.程式沒有通知,如果分割一個大檔案,使用者等了很久都不知道你在幹什麼,因此應該提供一個進度條。
2.發郵件的時候對檔案分割器的需求比較大,我們希望在發郵件的時候監測到郵件太大就自動分割檔案,分割同時發出一個協議檔案,描述了分割的步驟和順序,然後用戶端拿到分割後的檔案,再根據協議合并檔案。這樣檔案分割器就應該適用於可複用的組件。
3.檔案太大分割器會導致記憶體暴漲。問題在於代碼中的
例如我們要把1G的檔案分割成4份,這意味著一次就需要從硬碟上讀200多M,這樣對記憶體的需求就會暴漲。因此程式的演算法還需要改進。
開始重構
第一步首先要分離耦合,把表現層與業務層分離。
整個演算法放到Split函數裡面。接下來表現層只需要執行個體化一個分割演算法類即可。
這樣介面和類庫的代碼就順利解耦了。這樣的話我們就可以把分割類庫作為獨立的dll被Outlook等應用程式調用了。
然後我們考慮,MyFileSplitter類庫很可能會改變,特別是Split演算法的改變頻率可能更高。但是現在我們的表現層是依賴於邏輯層的,因此我們想到要在中間搭一層介面。這就要用到建立型模式。
表現層可以用原廠模式建立ISplitter的執行個體,這裡我們直接使用反射來建立執行個體。
這樣表現層就不與商務邏輯層直接產生依賴了。
然後我們考慮進度條,這涉及到對象與對象的通知關係,即觀察者模式。C#的委託事件機制其實就是這個模式的運用。
在ISplit介面裡添加SplitProgressEventHandler委託事件。之所以添加在介面裡是因為介面十分穩定。
Split分割檔案的實現方法中添加觸發進度條事件。
表現層,根據接收到的通知,更新進度條。
然後我們再解決記憶體暴漲的問題,我們不要一口氣讀太多的檔案內容,我們可以一次讀1M,讀到規定數量後才寫到一個小檔案中。另外,我們還可以使用多線程並行地去讀一個大檔案,這都是屬於演算法的更改,因此我們可以想到把Split方法劃分出去,用Strategy模式解耦。
另外我們還需要寫一個檔案合并器,這些都可能用到其他的很多設計模式。例如我們還可能需要支援網路上檔案的分割,斷點續傳技術等等,這些都是可能的變化點,需要我們考慮。
設計模式應用總結
設計模式建立在對系統變化點的基礎上進行,哪裡有變化點,哪裡應用設計模式。
設計模式應該以演化的方式來獲得,系統的變化點往往是經過不斷演化才能準確定位。
不能為了模式而模式,設計模式是一種軟體設計的軟力量,而非規範標準。不應誇大設計模式的作用。
2010.11.1