再沒有讀這章的時候就在想,上一章是factory那這章是不是就是Abstract Factory了。果不其然啊!
一樣的,在開始描述之前,援引wikipedia的定義來看看:
A software design pattern, the Abstract Factory Pattern provides a way to encapsulate a group of individual factories
that have a common theme. In normal usage, the client software would
create a concrete implementation of the abstract factory and then use
the generic interfaces to create the concrete objects that are part of the theme. The client
does not know (or care) about which concrete objects it gets from each
of these internal factories since it uses only the generic interfaces
of their products. This pattern separates the details of implementation
of a set of objects from its general usage.
這個非常學術的定義簡單點的描述就是,Abstract Factory是具體工廠類的抽象,可以建立出多個抽象工廠的具體派生工廠。應用程式無須知道當前使用的是什麼衍生類別,依然可以建立一組工廠的產品。很多的情況下,很多教材願意給出一個UIFactory的例子, 比如說像下面這個:(本著無圖無真相的原則,王道是一定要上的)
可以看到Application拿著GUIFactory的控制代碼(引用,指標?隨便)而不關注具體的是什麼衍生類別Win或者OSX,每次只要createButton就可以拿到一個button的引用而不知道什麼具體的什麼工廠的Button。顯然這樣讓應用程式可以和具體的UI解耦,從而可以輕鬆替換UI風格。
大致說了什麼是Abstract Factory之後,我們進入有點枯燥的實現。這裡的實現還是相當的抽象。
首先,第一步。就像前面描述的一樣,我們至少需要一個AbstractFactory的基類,用以後面具體的類型來做派生。值得注意的一點是,這裡的繼承關係比較複雜,還不是象上面圖中的直接繼承。下面是AbstractFactory類的大致實現
////////////////////////////////////////////////////////////////////////////////<br />// class template AbstractFactoryUnit<br />// The building block of an Abstract Factory<br />////////////////////////////////////////////////////////////////////////////////<br /> template <class T><br /> class AbstractFactoryUnit<br /> {<br /> public:<br /> virtual T* DoCreate(Type2Type<T>) = 0;<br /> virtual ~AbstractFactoryUnit() {}<br /> };<br />////////////////////////////////////////////////////////////////////////////////<br />// class template AbstractFactory<br />// Defines an Abstract Factory interface starting from a typelist<br />////////////////////////////////////////////////////////////////////////////////<br /> template<br /> <<br /> class TList,<br /> template <class> class Unit = AbstractFactoryUnit<br /> ><br /> class AbstractFactory : public GenScatterHierarchy<TList, Unit><br /> {<br /> public:<br /> typedef TList ProductList;</p><p> template <class T> T* Create()<br /> {<br /> Unit<T>& unit = *this;<br /> return unit.DoCreate(Type2Type<T>());<br /> }<br /> };
(現在的代碼編輯器好差啊!)
注意,我們這裡用到了GenScatterHierarchy這個模板。(這個模板不明白的話只好看看第三章了)這個模板可以協助我們產生了一堆分散的類。書中給出了這樣一個例子
typedef Loki::AbstractFactory<LOKI_TYPELIST_3(Soldier, Monster, SuperMonster)> AbstractEnemyFactory;
這樣一個語句卻為我們產生了一個分散的類階層。
(圖一)
現在看這個類,我們至少知道了一些資訊,比如AbstractEnemyFactory從AbstractFactoryUnit<Soldier>這樣的一組類繼承下來。但是又有很多不明白的,如AbstractFactoryUnit怎麼工作呢?或者要怎麼來實現一個AbstractFactoryUnit的衍生類別,然後又如何讓這個ConcreteFactoryUnit和ConcreteFactory合作呢?帶著很多的疑問,我們進入了下一個ConcreteFactory的實現就豁然開朗了(其實沒有這麼快的,這個一個很艱難的過程)。
這裡有個ConcreteFactory的實現,這裡用到了GenScatterHierarchy的兄弟GenLinearHierarchy。
////////////////////////////////////////////////////////////////////////////////<br />// class template OpNewFactoryUnit<br />// Creates an object by invoking the new operator<br />////////////////////////////////////////////////////////////////////////////////<br /> template <class ConcreteProduct, class Base><br /> class OpNewFactoryUnit : public Base<br /> {<br /> typedef typename Base::ProductList BaseProductList;</p><p> protected:<br /> typedef typename BaseProductList::Tail ProductList;</p><p> public:<br /> typedef typename BaseProductList::Head AbstractProduct;<br /> ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)<br /> {<br /> return new ConcreteProduct;<br /> }<br /> };<br />////////////////////////////////////////////////////////////////////////////////<br />// class template ConcreteFactory<br />// Implements an AbstractFactory interface<br />////////////////////////////////////////////////////////////////////////////////<br /> template<br /> <<br /> class AbstractFact,<br /> template <class, class> class Creator = OpNewFactoryUnit,<br /> class TList = typename AbstractFact::ProductList<br /> ><br /> class ConcreteFactory<br /> : public GenLinearHierarchy<<br /> typename TL::Reverse<TList>::Result, Creator, AbstractFact><br /> {<br /> public:<br /> typedef typename AbstractFact::ProductList ProductList;<br /> typedef TList ConcreteProductList;<br /> };
初看這個代碼的時候更糊塗了,為什麼OpNewFactoryUnit和之前的Unit好像沒有什麼關聯?這樣怎麼建立對象呢?還有這個ConcreteFactory為什麼不直接從AbstractFactory來,要搞這麼多奇怪的GenLinearHierarchy的使用呢?我們還是先來看看這個具體的語句聲明以後產生的類圖吧
typedef Loki::ConcreteFactory<AbstractEnemyFactory, Loki::OpNewFactoryUnit,
LOKI_TYPELIST_3(SillySoldier, SillyMonster, SillySuperMonster)> EasyLevelEnemyFactory;
(圖二)
儘管這個圖片比較小,但是我們依然能夠清楚的把握到2點:
1. EasyLevelEnemyFactory還是從AbstractEnemyFactory繼承下來的,只是中間經曆了很多過程。所以我們還是可以像普通的抽象工廠一樣的工作。
2. 這個抽象層次中產生的類例如OpNewFactoryUnit<SillySoldier, AbstractEnemyFactory>繼承與AbstractFactory,也就是說他們繼承於AbstractFactoryUnit<Soldier>。(請參照圖一)
所以看到現在我們再回過頭來看AbstractFactory中的Create()函數的時候就不足為奇了:
假設我們有如下這樣的調用:
std::auto_ptr<AbstractEnemyFactory> easyFactory(new EasyLevelEnemyFactory);
Soldier *s;
s = easyFactory->Create<Soldier>();
通過分析可以知道,easyFactory這個AbstractEnemyFactory的智能指標指向了一個EasyLevelEnemyFactory的執行個體,在Create<Soldier>()函數調用的時候發生了什麼呢?首先調用了AbstractFactory的Create函數(因為ConcreteFactory根本沒有這個介面)
template <class T> T* Create()<br /> {<br />// 把自己轉化成一個AbstractorFactoryUnit<Soldier>的引用。<br />// 當然自己實際上是OpNewFactoryUnit<SillySoldier, AbstractEnemyFactory><br /> Unit<T>& unit = *this;<br />//調用誰的DoCreate呢??當然是OpNewFactoryUnit<SillySoldier, AbstractEnemyFactory>的<br />//因為AbstractorFactoryUnit沒有實現這個介面<br />//為什麼要Type2Type呢?<br />//模板函數不支援偏特化,這裡可以通過這個模板類型實作類別似的功能<br />//比如你要為某個特定的T做些什麼,例如加個特殊參數。。<br /> return unit.DoCreate(Type2Type<T>());<br /> }
後面的事情就是DoCreate的實現啦。書中給出了一個傳統的實現就是每次都New一個,還有一個實現就是所謂的prototype模式的應用,這就不是AbstractFactory討論的重點了。
這裡來總結一下,可以看出這個模型的設計著有鬼神之才。如此繁複的模型看著都覺得麻煩,那設計出來的人豈不是。。。
不管了, 關鍵的問題是要理解。所以簡單點的說就是AbstractFactory和ConcreteFactory套用GenScatterHierarchy和GenLinearHierarchy產生了一個巨大的階層,完成了抽象工廠模型的建立。理解起來很麻煩,但是用起來,確實很爽。而且那些具體的Unit還和Factory沒有複雜的耦合,確實是吐血推薦了:)