淺析設計模式之FactoryMethod

來源:互聯網
上載者:User

前些日子把GoF的設計模式看完了,不過有些地方理解的還不是很深入,而且有段時間不看也有些忘記。當時感觸頗深,讀後就只有仰止的份:真不愧是大家手筆,把OO真正的精髓都體現在了這薄薄的一本書中了。

這本書的完整的書名是“Design Patterns - Elements of Reusable Object-Oriented Software”,注意這裡的reusable這個詞,“軟體複用”的重要性我想應該不用我再多囉嗦了,它是高效率、高品質、高可用的軟體的基礎。從軟體設計的混沌時期到結構化、模組化程式設計,面向過程的程式設計範型,到物件導向OO程式設計範型,到泛型程式設計GP,到設計模式,到基於組件的編程,到中介軟體……“軟體複用”一直是程式員不斷追求的目標。“複用”是分為不同的層次的,我們在C中用到的庫函數實際上是結構化程式設計範型中的源碼層級的複用;Java, .Net, Delphi中使用的類庫中等可以說OO裡面類層次上 的、功能性的複用;組件複用實際上是一個設計良好的低耦合(僅僅通過對外提供的一些介面)、高內聚的小型軟體系統的複用;中介軟體和組件類似,但複用的層次更高;而設計模式則是系統架構、OOD思想層次上的複用。

衡量某種類型的複用的好壞的標準應該是這種複用能夠解決的問題的多少。某種類型的複用的層級越高,就意味著它能解決的問題越多。個人覺得,思想的複用才是最進階別的複用,掌握了某種思想能解決的問題才是最多的。比如演算法“歸併排序”這個具體的演算法:根據這個演算法,我們能夠在O(n*log(n))的時間複雜度上解決所有的排序問題,這確實已經是個很不錯的複用了。但也僅僅限於排序問題,出了這個領域,本演算法也就沒有用武之地了。這是一個比較底層次上的複用。而如果我們掌握了歸併排序的設計思想--分治法的思想,那我們能解決的問題就要多得多得多了:快速排序、二分檢索、求最大最小元素、選擇問題、矩陣乘法,甚至不限於電腦科學的其他領域的問題。。。這就是更高一個層次的複用了。

大家可能會有這樣的困惑,學了C++,學了Java這些物件導向的程式設計語言,也基本搞清楚了OO的3大特性:封裝、繼承、多態,但卻不知道這些語言層面的特性應該怎麼去用。C++中的虛函數、純虛函數、虛函數表的實現機制、多繼承、虛繼承、物件建構的順序可以搞的很透徹、很清楚,(當然Java, .Net中也有類似概念,這裡不再一一列舉 )卻不知道在軟體設計中怎麼使用。怎麼把問題從現實的域中映射到電腦中?什麼時候需要定義一個類?各個對象之間應該怎樣互動?什麼時候把一個成員函數定義為virtual? 設計模式會告訴我們答案。

因此,可以說,不懂設計模式的話就不能說真正理解OO。 設計模式這種設計思想層次上的複用,是進階軟體工程師、系統架構師的必修課。

今日突發奇想,如果每個模式看完之後都把自己的理解、思考用通俗易懂的語言寫出來,既能夠加深自己的理解,又可以讓一個初學者能夠在最短的時間內掌握某個模式的精髓,一舉兩得,豈不快哉?

本文內容純屬一家之言,旨在根據自己的理解協助初學設計模式者入門,兼拋磚引玉。在下才疏學淺,如有不對的地方,還請賜教。我的郵箱為(a*4)lex[at]21cn.com (//"(a*4)"請替換成4個a,謝謝)

第一站,建立型模式之Factory 方法(Factory Method)。什麼是Factory 方法呢?首先,大家得對這個模式有個基本的瞭解。工廠是做什麼的?就是生產產品(product)吧。如果我們調用它的constructor,product = new Product(),這相當於是“自給自足”。如果有個叫Creator的類,我們通過調用它的某個方法FactoryMethod()來得到實際的product,那麼這個方法就叫做Factory 方法。說白了,就是我們不去直接調用Product的constructor(有時為了強制必須通過Factory 方法來產生對象,甚至把Product類的所有版本的constructor都設定成非public的,這樣的情況下我們就根本無法直接使用new來“自給自足”了)。

根據GoF的《設計模式》書中的介紹,我們先來看看Factory 方法比較權威的定義。
名  稱
 Factory Method(原廠模式)
 
意  圖
 定義一個用於建立對象的介面,讓子類決定執行個體化哪一個類。Factory Method 使一個類的執行個體化延遲到其子類。
 
適  用  環  境
 當一個類不知道它所必須建立的對象的類的時候。

當一個類希望由它的子類來指定它所建立的對象的時候。

當類將建立對象的職責委託給多個協助子類中的某一個,並且你希望將哪一個協助子類是代理者這一資訊局部化的時候。
 
結  構

 

光看這個解釋和類圖,感覺很晦澀,舉個例子吧。

假如我們要寫個類似MS Office這樣的軟體,同時提供Word文文書處理和Excel試算表的功能。

那麼利用Factory 方法模式,我們可以得到下面的類圖所示的結構。

提示:這是個標準的UML中的類圖,注意名稱用斜體字書寫的類或者方法都是抽象的。抽象類別不能被執行個體化,只能用來引用某個具體子類的執行個體;而抽象方法就是會表現出“多態性”的方法,也就是說會非調用該執行個體所屬於的具體子類中相應版本的非抽象方法。 圖中那個docs表示OfficeApp中包含有一個Document對象的集合 docs,就象實際中的一個程式可以開啟多個文檔那樣。

具體的代碼我就不寫了,就就著類圖來說明吧:在OfficeApp中有個非抽象(考慮這裡為什麼是”非抽象“的方法?當然也可以把它定義成一個抽象的方法,然後把相同的邏輯在每個子類中相應的非抽象方法中都重複地粘貼一遍,但這樣的代碼不但冗餘難於維護,而且還會造成潛在的不一致性)的方法NewDocument,我們需要在該方法中建立一個具體的Document對象(或者是ExcelDoc或者是WordDoc),以及一些後續操作,比如象代碼所示的那樣,把建立的這個新文檔添加到當前的所有文檔列表docs中去(docs.Add(doc)),然後再開啟當前的文檔(doc.Open()。但這裡問題出來了,我們在此時並不知道究竟應該建立那個具體的子類(究竟是WordDoc呢還是ExcelDoc呢?),我們唯一知道的只有它們共同的那個不能被執行個體化的抽象父類Document。
這裡就是“多態“大顯身手的地方了,我們在WordApp中定義了一個抽象方法CreateDocument(返回一個Document的指標或者引用),而在WordApp和ExcelApp中相應版本的具體的CreateDocument方法中,則分別訪問WordDoc和ExcelDoc的constructor來實現具體的Document的子類的建立,分別返回一個WordDoc或者ExcelDoc的指標或引用。
 
好了,假設我們建立了一個具體的WordApp對象myWordApp,那麼當使用者點擊“建立”菜單的時候,我們的處理就只需要簡單地調用一下myWordApp.NewDocument()就行了,這個函數是從它的基類OfficeApp中繼承下來的,但會根據“多態性”建立一個AppDoc類型的具體類型。

這裡,我們說CreateDocument()就是一個Factory 方法。它定義一個用於建立對象(Document)的介面,讓子類(WordApp或者ExcelApp)決定執行個體化哪一個類(WordDoc或者ExcelDoc)。CreateDocument()這個Factory 方法使一個類(Document的子類:WordDoc或者ExcelDoc)的執行個體化延遲到其子類(OfficeApp的子類:WordApp或者ExcelApp)。

從這個例子中,我們把Factory 方法模式抽象到一般情況,就得到最前面的那張類圖。

這張圖和上面的那個例子中的例圖是很容易對應起來的,只不過這裡省略了其他一些無關緊要的、與本模式無關的成員方法。

Factory 方法還有一種用法,有時候並不需要在Creator這邊實現多級的繼承關係,只需要一個具體的Creator類就行了,其中的Factory 方法根據某個判定依據分別產生不同的ConcreteProduct並返回其指標或者引用。

 

著作權聲明:本文著作權者為(a*4)lex[at]21cn.com 。遵循GPL License,歡迎自由傳播。請尊重他人的勞動成果,轉載請註明出處,謝謝! 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.