1. 程式人生 > >Aha!設計模式(3)-抽象工廠(2)

Aha!設計模式(3)-抽象工廠(2)

動機

《設計模式》引言中對於動機的說明如下:

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

簡單地說:就是設計模式的應用例項。

回到抽象工廠模式的動機。

考慮一個支援多種視感(look-and-feel)標準的使用者介面工具包,例如 Motif和Presentation Manager。不同的視感風格為諸如滾動條、視窗和按鈕等使用者介面“視窗元件”定義不同的外觀和行為。為保證視感風格標準間的可移植性,一個應用不應該 為一個特定的視感外觀硬編碼它的視窗元件。在整個應用中例項化特定視感風格的視窗元件類將使得以後很難改變視感風格

《設 計模式》成書很早,所以書中會出現許多過去的軟體和技術,例如上文Moti和Presentation Manager。這裡建議大家不必過分在意這些名詞,能夠理解作者意圖即可。上面的文字中忽略例如的部分也不會有任何問題,只要能找到類似的場景就好,例 如Linux作業系統的主題就是一個不錯的例子。除了表示方式不同之外,動作方式也會有所不同。可以想象:如果將所有和主題相關的程式碼都寫在一個類裡,代 碼勢必會變得很複雜,最後的結果就是得無法維護和擴充套件。

為解決這一問題我們可以定義一個抽象的 WidgetFactory類,這個類聲明瞭一個用來建立每一類基本視窗元件的介面。每一類視窗元件都有一個抽象類,而具體子類則實現了視窗元件的特定視 感風格。對於每一個抽象視窗元件類, Wi dgetFactory介面都有一個返回新視窗元件物件的操作。客戶呼叫這些操作以獲得視窗元件例項,但客戶並不知道他們正在使用的是哪些具體類。這樣客 戶就不依賴於一般的視感風格,如下頁圖所示。

每 一種視感標準都對應於一個具體的 WidgetFactory子類。每一子類實現那些用於建立合適視感風格的視窗元件的操作。例如, MotifWidgetFactory的Crea teScrollBar操作例項化並返回一個Motif滾動條,而相應的PMWidgetFactory操作返回一個Presentation Manager的滾動條。客戶僅通過WidgetFactory介面建立視窗元件,他們並不知道哪些類實現了特定視感風格的視窗元件。換言之,客戶僅與抽 象類定義的介面互動,而不使用特定的具體類的介面。

面 向物件中解決這類一問題的方法只有一個,就是利用多型,首先建立各種視窗組建的抽象類,然後在每種主題中為相應的組建準備具象類。上圖中的Windows 和ScrollBar就是視窗組建的抽象類,而PMWindow,MotiWindow,PMSrollBar,MotiScrollBar就是對應的具 象類。

對於視窗組建的利用者Client來說,並不需要知道各個視窗組建的具象類,只有知道元件是某種Window或者某種ScrollBar即可。但是還有一個問題:Client在使用元件時雖然可以不知道元件具象類資訊,但構建元件的時候無論如何也沒有辦法繼續裝糊塗。

解決這個問題想法就是將構建視窗元件的部分封裝的到一個類中。名字可以叫WidgetFacroty,它根據主題資訊生成對應的視窗元件,壞事交給別人做。這就是簡單工廠模式。簡單工程模式依然不夠完美:因為當增加主題的時候,仍然需要對工廠類進行一定的修改。

終於到了主角出場的時候了。

這裡繼續請出面向物件的絕招:多型。我們可以準備一個工廠的抽象類,然後為每種主題準備具象類。每種具象工廠類負責生成對應主題的視窗元件。在需要更換主題時,更換具象工廠類即可。

WidgetFactory也增強了具體視窗元件類之間依賴關係。一個 Motif的滾動條應該與Motif按鈕、Motif正文編輯器一起使用,這一約束條件作為使用 MotifWidgetFactory的結果被自動加上。

Client得到視窗元件的方式只有通過指定的具象工廠類一種方式,這樣就從結果上決定了哪些具象視窗組建類一起協同工作。

作業題解答

前一篇文章的最後,留了一個尾巴,關於依賴關係的畫法的。其實這本不應該一個問題。因為面向物件的一個基本原則就是降低耦合以增加可維護性和可擴充套件性,所以要儘量對抽象類程式設計,最好只和抽象類有單向的依賴關係。指向具象類的依賴雖然不能完全迴避,但這種關聯線最好只有一條。否則就很有可能是那種"長得就犯法“的設計。

注:

本文中藍色粗體文字都引自《設計模式》一書。

覺得本文有幫助?請分享給更多人。

閱讀更多更新文章,請掃描下面二維碼,關注微信公眾號【面向物件思考】