設計模式中的生成模式(Creational Patterns),整理出一套經驗及法門,告訴我們各種間接產生物件的應用情境。在這些情境中,透過特定的形式讓不同的類別互動,間接產生所需的物件,從中獲得頗多的利益。

剛接觸生成模式時,會發現其中許多生成模式的名稱,都有Factory(工廠)這個字。沒錯,設計模式十分講究語彙,使用「Factory」這個字時,代表這個模式是專門用來製造某種物件,而且通常會用「Product」指涉由Factory製造出來的物件。

常見的設計模式中,有3個以Factory概念為中心的生成模式,它們分別是:Simple Factory Method、Factory Method、以及Abstract Factory。這3種Factory,都是負責產生物件實體的,但複雜度有高低差異,適合的應用情境亦有不同,但基本上,大多數情況,只需要最單純的「Simple Factory Method」。

我建議先從Simple Factory Method著手,隨著系統的演進,等到真正複雜的應用浮現之後,再採用重構(Refactoring)技巧,將Simple Factory Method依需求演化成Factory Method或Abstract Factory。由於這3種模式血統出自同宗,所以一般來說,很容易演化,而且不會對既有的系統造成太大的衝擊。

所謂Simple Factory Method,是指透過某個專門類別的特定Method,產生符合某一既定產品介面的實際產品。必須要注意的是,即便是最簡單的Simple Factory Method,都有各種不同的變形及實作方式。第一種實作的方式,如圖一。


圖一:Simple Factory Method的實作。


BaseClass是抽象的類別,有各種可能的衍生類別,也就是各種可能的實作。在抽象的父類別BaseClass中,提供一個靜態的Method--createProduct(),回傳的型別恰好就是BaseClass。BaseClass還定義了一個叫做service()的Method,代表所有衍生類別提供的不同服務實作。

Simple Factory Method的應用情境,例如用戶端有可能使用LDAP、資料庫的帳號/密碼,甚至客製化的方式進行認證。所以,系統會具體產生的類別,必須是可變的。對於用戶端來說,必須有一個共通的規範(例如,所有的認證類別都能夠認證),否則用戶端程式便無法加以運用。

在上述的類別圖當中,抽象類別BaseClass扮演的就是共通規範的角色。實際上被產生的產品(ClassImplA、ClassImplB、ClasSImplC),都是繼承並實作這個BaseClass。

以用戶端來說,它們都是遵守規範(也就是BaseClass)的實體,用戶端也不在意它們確切的型別究竟為何,只要它們遵守BaseClass的規範,而且都能夠提供service()供用戶端程式之用。對用戶端而言,就因為根本不知道確切的型別,所以當這型別改變時,不會影響到用戶端。

針對可能會產生出來的產品,制定一個規範是很重要的,這個規範代表著用戶端可以期待產品提供的服務。

當設計的系統,面臨的局面是:(1)會依需要產生若干個分屬於不同類別的物件,(2)想要用同一段用戶端程式碼使用這些物件,(3)這些不同的類別,可以整理出一個共通的介面。符合以上條件就很適合應用Simple Factory Method,幫助我們產生所需的物件。

前文所提到的情境,(1)會依需要產生各種不同的認證類別,(2)會在同一段用戶端程式碼中,以相同的方式使用各種不同的認證用類別,(3)這些不同的認證用類別,可以整理出一個共通的介面。此時,應用Simple Factory Method的時機就很明顯了。針對這個例子,我們設計成如圖二。


圖二:以Simple Factory Method設計包含多種認證方式的系統。


這樣的設計方式,基本上和前圖一樣,用戶端程式的寫法:


Authenticator auth =
Authenticator.createAuthenticator();
auth.authenticate(id, passowrd);


使用Simple Factory Method時,有兩大應用要點:(1)要針對可能會產生的各種不同類別,萃取出一個共通的介面或Base Class(2)將如何產生用戶端會需要的類別實體的邏輯封裝到單一Method(無論這個Method是否隸屬於Base class)。所以,剛才的例子稍加改變如圖三。


圖三:萃取一個共通的介面,將邏輯封裝到單一的Method,可以將各類別的角色釐定得更清楚。


添加另一個獨立的類別AuthenticatorFactory,將原先定義在Authenticator中的createAuthenticator(),抽離至AuthenticatorFactory,可以將各類別的角色釐定得更清楚。讓單一個類別專職產生,而讓Base Class更專門地扮演介面規範的角色。這種設計同樣屬於Simple Factory Method。

在認證類別的例子中,createAuthenticator()產生物件的邏輯,主要是依據系統的組態設定,決定究竟要回傳的認證類別;但是實際應用Simple Factory Method時,我們也會時常遭遇到要產生的物件,它的類別是取決於當下用戶端所取得的某些輸入值。這時候,只需要稍加更動creation method即可,例如:


只需要將控制產生物件的輸入值(Input intpu)添加到creation method中,進一步在creation method中讀取輸入值,再決定應如何產生相對應的類別物件即可。

《作者簡介》王建興
清華大學資訊工程系的博士研究生,研究興趣包括電腦網路、點對點網路、分散式網路管理、以及行動式代理人,專長則是Internet應用系統的開發。曾參與過的開發專案性質十分廣泛而且不同,從ERP、PC Game到P2P網路電話都在他的涉獵範圍之內。

相關閱讀:
探索產生物件的技巧(1)當心隨手New一下引發的衝擊效應
探索產生物件的技巧(3)鬆綁程式內工廠與產品的關聯性
探索產生物件的技巧(4)抽象可抵擋變動引發的星星之火
探索產生物件的技巧(5)維持類別僅存在一份實例的設計方法
探索產生物件的技巧(6)受夠重新開機?試試自行管理記憶體
探索產生物件的技巧(7)避免時效性不高的重複性動作
探索產生物件的技巧(終)間接產生物件的訴求:降低相依性

熱門新聞

Advertisement