1.工廠方法
(factory method)
模式工廠方法模式的意義是定義乙個建立產品物件的工廠介面,將實際建立工作推遲到子類當中。核心工廠類不再負責產品的建立,這樣核心類成為乙個抽象工廠角色,僅負責具體工廠子類必須實現的介面,這樣進一步抽象化的好處是使得工廠方法模式可以使系統在不修改具體工廠角色的情況下引進新的產品。
工廠方法模式結構示意圖
工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先完全實現『開-閉 原則』,實現了可擴充套件。其次更複雜的層次結構,可以應用於產品結果複雜的場合。
工廠方法模式很好用,但在**層面上,為每乙個產品都編寫乙個對應的工廠,這無疑很麻煩,而且不同的product
要寫不同
creator
。想想你在寫乙個
gui庫,基本控制項為
widget
類,由其派生下了
textbox
,button
,label
等幾十個控制項,那你需要為這幾十個控制項分別編寫對應的
concretecreator
。天,這太麻煩了吧!而如果你還要寫乙個
rpg小遊戲,需要從
person
類派生下如
npc,
hero
,emeny
,ally
等又是十幾個類,而且還要編寫乙個對應於
person
的creator....
2.模板實現工廠方法模式
面對這種型別造成的多型,c++
模板就要出場了。現在情況是這樣的,
product
和concreteproduct
都已經寫好,我們要為其編寫對應的工廠類。可以看出來,
product
對應對creator
,concreteproduct
對應於concretecreator
。也就是說,如果想編寫通用的
concretecreator
,就得將
concreteproduct
抽象,想編寫通用的
creator
,就得將
product
抽象。而我們最後會將這
2者都抽象了。
首先編寫通用的concretecreator
[cpp]view plain
copy
// 具體工廠類
// product為抽象產品,concreteproduct為具體產品
template
<
typename
product,
typename
concreteproduct>
class
concretecreator
};
注意createproduct()是靜態的,是因為該函式要被儲存起來的,靜態函式只需儲存其函式指標即可,而普通的成員函式還要額外儲存乙個物件指標,這無疑更麻煩了。 也就是我們不需要這樣用:
[cpp]view plain
copy
concretecreatorconcretecreator;
product* p = concretecreator.createproduct();
只需要這樣寫:
[cpp]view plain
copy
product* p = concretecreator::createproduct();
下面是creator
的實現[cpp]view plain
copy
// 抽象工廠
// product為抽象產品
template
<
typename
product>
class
creator
private
: creator() {}
~creator() {}
creator(creator&);
// 對外介面
public
: typedef
product* (*createproductdelegate)( );
// 生產產品的產品
typedef
std::mapmapregistercreatoritem;
// 根據具體產品生成具體工廠
// 並將具體產品註冊進抽象工廠
// concreteproduct為具體產品
template
<
typename
concreteproduct>
void
registercreator(
const
std::string& _type)
// 刪除所有具體工廠
void
unregisterallcreators()
// 生產型別為_type的產品
// 失敗返回0
product* createproduct(const
std::string& _type)
return
0;
} private
: mapregistercreatoritem mconcretecreators; // 儲存所有註冊過的具體產品
};
下面來簡單解釋一下上面的**。
首先creator實現了單例模式,這只是為了方便使用,你也可以不實現為單例。
creator裡面儲存了所有註冊過的具體工廠,具體工廠在註冊時被構建,每個具體工廠對應乙個名字(
string
型別)。
createproduct即為工廠方法,外部通過此介面建立產品,建立時僅需提供具體工廠的名字即可。
我們以rpg
遊戲那個作為例子。要建立乙個
person
的creator
,可以這樣寫
[cpp]view plain
copy
typedef
creatorpersoncreator;
personcreator& factory = personcreator::instance();
factory.registercreator("person"
);
factory.registercreator("hero"
);
factory.registercreator("npc"
);
這樣即完成了註冊過程,你可以繼續為其他型別註冊具體工廠。
要建立乙個npc,可以這樣寫
[cpp]view plain
copy
person* npc = factory.createproduct(
"npc"
);
[cpp]view plain
copy
3.優缺點
此方法的優點很明顯,就是用起來很方便。由於creator
支援不同型別,你不要為不同的產品編寫不同的
creator
。而且其提供了註冊具體工廠的方法,你僅需要寫一行**即可為具體產品生成具體的工廠,而不需要編寫專門的類。
而且其註冊過程是可以在執行時修改的,也就是說你可以在執行時動態地註冊或反註冊具體工廠,這樣靈活性就很大了。
缺點的話就是不支援構造函式引數,也就是說在建立產品時不支援引數。當然可以為不同數量引數編寫具體的模板creator
。但其實個人並不提倡提供無參建構函式。我認為像這類產品類,都應該提供乙個無參的建構函式版本,然後提供
get,
set函式來修改內部成員變數。
C 模板實現佇列
我準備練習一下模板的知識,然後自己實現vector類。在這之前,先用模板實現乙個佇列來熱身吧。佇列的底層是鍊錶。主要是熟悉一下模板的寫法。另外,就是模板的定義和實現都要寫在乙個檔案中 export關鍵字可以避免這樣。還沒用過 所以倒數第二行我加了個 include queue.hpp 只能是hpp,...
設計模式之 簡單工廠模式 C 模板實現
同樣以汽車廠生產汽車為例進行說明。如下 include include using namespace std class ccarbase virtual ccarbase protected ccarbase ccarbase const string name m name name stri...
c 模板之 抽象工廠
完成 見 1.設計模式中抽象工廠的泛型 實現 2.c 自動生成模板 的例子 具體實現見 c 泛型程式設計 之 自動生成 the loki library this code accompanies the book alexandrescu,andrei.modern c design generi...