一. 工廠方法(factory-method)模式
1. 意圖
定義一個(gè)創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪個(gè)產(chǎn)品類。工廠方法使一個(gè)對(duì)象的創(chuàng)建延遲到子類。
2. 適用性
當(dāng)一個(gè)類不知道它要?jiǎng)?chuàng)建的對(duì)象的類時(shí)。
當(dāng)一個(gè)類希望由它的子類來決定創(chuàng)建哪個(gè)類的對(duì)象時(shí)。
當(dāng)一個(gè)類決定將創(chuàng)建對(duì)象委托給多個(gè)子類,并且希望將那個(gè)子類是代理這一信息局部化的時(shí)候。
3. 結(jié)構(gòu)
4. 參與者
l Creater:
聲明工廠方法的抽象類,工廠方法返回一個(gè)產(chǎn)品類(Product)。
可以調(diào)用工廠方法返回一個(gè)產(chǎn)品對(duì)象。
l ConcreteCreater:
重定義工廠方法,以返回一個(gè)特定的product。
l Product:
產(chǎn)品抽象類,給用戶提供一致的產(chǎn)品接口。
l ConcreteProduct:
特定的產(chǎn)品,實(shí)現(xiàn)product接口。
5. 效果
工廠方法將特定的類的實(shí)例化延遲到子類,而且返回product接口,使用戶代碼不用和具體類打交道,一致的對(duì)待Product。所以在用戶要加入新產(chǎn)品的時(shí)候,無需更改客戶代碼,只需加入一個(gè)新的ConcreteProduct和ConcreteCreater即可,這個(gè)也是遵 守了“開放封閉原則”。
連接平行的類層次,上面的結(jié)構(gòu)圖中,ConcreteCreater1對(duì)應(yīng)創(chuàng)ConcreterProduct1而ConcreteCreater2對(duì)應(yīng)創(chuàng)建ConcreterProduct2。所以creater和product的類層次是平行的,用戶只需選定一個(gè)Creater,就創(chuàng)建出對(duì)應(yīng)product。像是一個(gè)map一樣,不會(huì)出現(xiàn)牛頭不對(duì)馬嘴之態(tài)。
6. 實(shí)現(xiàn)及變體
Creater有兩種實(shí)現(xiàn),一種就是抽象的工廠方法,具體實(shí)現(xiàn)留到子類。另一種就是有一個(gè)缺省的實(shí)現(xiàn),子類也可以重新實(shí)現(xiàn)這個(gè)方法。這種方法使用于真的有一個(gè)默認(rèn)的Product需要實(shí)例化的這種情況。
帶參數(shù)的工廠方法,這種情況可以創(chuàng)建多種產(chǎn)品,不過有個(gè)限制就是所有產(chǎn)品都要實(shí)現(xiàn)product接口,否則就失去工廠方法的意義了。代碼如下:
Product* ConcreteCreater1::FactoryMethod(int nID)
{
If(nID == BUTTON)
return new button;
}
Else if(nID == BOX)
return new box;
…
用模板實(shí)現(xiàn),省略創(chuàng)建子類。
class Creater
public:
virtual Product* FactoryMethod() = 0;
};
template<class theProduct>
class TempCreater: public Creater
virtual Product* FactoryMethod();
Product* TempCreater<theProduct>::FactoryMethod()
return new theProduct;
使用這個(gè)模版客戶端只需定義產(chǎn)品,而不需定義creater的子類。
二. 程序舉例
在一個(gè)ACT游戲中,主角過關(guān)過程中有許多敵人,如狼(wolf),蝙蝠(bat),老怪(BOSS),在每一關(guān)的剛開始就要?jiǎng)?chuàng)建許多不同的敵人,如果不用工廠方法,則把所有的創(chuàng)建任務(wù)都放在了客戶代碼中,則一個(gè)代碼不易擴(kuò)充和修改,二是代碼很雜亂。而用了工廠方法則可以克服這兩個(gè)缺點(diǎn)。比如你增加一個(gè)新的敵人-恐龍,則只需增加一個(gè)恐龍類(ConcreteProduct),再增加一個(gè)創(chuàng)建恐龍的類(ConcreteCreater )就OK了。
源碼如下:
三. 相關(guān)模式
Abstract Factory經(jīng)常用工廠方法來實(shí)現(xiàn)。
工廠方法通常在Template Methods中被調(diào)用。
Prototypes不需要?jiǎng)?chuàng)建Creater的子類。但是,它們通常要求一個(gè)針對(duì)Product類的Initialize操作。Creater使用Initialize來初始化對(duì)象。而Factory Method不需要這樣的操作。
四. 參考文獻(xiàn)
《設(shè)計(jì)模式精解》 清華大學(xué)出版社, 熊杰譯。
《設(shè)計(jì)模式可復(fù)用面向?qū)ο筌浖幕A(chǔ)》 機(jī)械工業(yè)出版社, 四人團(tuán)著。