工厂对象模式简介
在GoF的《設計模式》一書中,對Factory Method/Object Method 意圖描述如下:
定義一個用于創建對象的接口,讓子類決定實例化是哪一個類。 Factory Metho是一個類的實例化延遲到其子類。
其結構圖如下:
其中, 類 Product 定義了一類對象的接口。 ConcreteProduct 實現 Product 的接口。 Creator是工廠方法的包裝器。ConcreteCreator 類實現Creator的接口。基于以上結構,每個ConcreteProduct必須帶有一個 ConcreteCreator, 用來產生特定的ConcreteProduct。
這種實現的缺點,在《設計模式》一書中也提到過一點 是客戶可能僅僅想創建一個特定的 ConcreteProduct 對象,但必須額外創建 Creator 的子類。 在ConcreteProduct 的演化上造成額外的工作量。 另一點從代碼簡潔之道角度來看,每一個 ConcreteCreator 的實現都幾乎一樣,就像一幕幕乏味的樣板戲,簡直就是雞肋。
那么如何改進呢?
?
用boost factory & boost function實現對象工廠
?
文件:ObjectFactory.h
?
??
[cpp]?view plain?copy?
以上代碼中,模板ObjectFactor接收兩個參數,第一個參數IdType是用來標識是哪種子類對象的關鍵字。ObjectType是基類對 象類型。也就是上面結構圖中的Product。為了實現創建ConcreteProduct對象的方法,我們需要獲得每個子類對象的構造函數信息,通過 RegisterObjectCreator方法我們將子類對象的構造函數信息保存在工廠中。? 那么哪種數據結構表示構造函數信息呢? 通過普通函數指針,好像行不通。在這里我們用到了 boost::function,它可以將任意的函數信息封裝到function object對象中,從而可以實現賦值,調用等操作。
以上工廠實現中我們將任意類型的默認構造函數信息用 boost::function 進行封裝,表示成 typedef boost::function< ObjectType* () > CreatorType;
后面我們就是建一張表來關聯IdType與它所對應ConcreteProduct的構造函數信息。這里我們直接用 std::map關聯容器來存儲。
RegisterObjectCreator用于注冊ConcreteProduct對象的構造函數信息。
MakeObject用于根據傳入的IdType來生成對應的ConcreteProduct對象。注意這一句 (iter->second)(); 它返回指向ObjectType對象的指針。? 實際上iter->second返回是一個CreatorType 類型函數對象,對一個函數對象進行()調用。因為CreatorType是對構造函數的封裝,因此實際上是調用ConcreteProduct的構造函數 生成一個ConcreteProduct對象。 后面會看到 CreatorType 是我們用 boost::factory 封裝的,它默認會調用new操作符從堆上構造一個ConcreteProduct對象。
?
?
如何使用對象工廠
?
我們來實現GoF Factory Method結構圖中類似的代碼。
首先我們定義幾個類:
Product????????????????? --? 產品類接口封裝,定義了類對象的接口。
ConcreteProductA? --? 具體的產品A,該類 實現 Product 的接口。
ConcreteProductB? --? 具體的產品B,該類 實現 Product 的接口。
文件:Product.h
?
?
[cpp]?view plain?copy?
文件:ConcreteProductA.h
?
[cpp]?view plain?copy?
?
文件:ConcreteProductB.h
?
[cpp]?view plain?copy?
?
下面我們來測試上面的對象工廠。
文件: Main.cpp
?
[cpp]?view plain?copy??
?
在以上測試中,我們首先生成一個對象工廠,這里我們以std::string作為IdType來標示是哪種類型的ConcreteProduct。
然后向工廠中注冊具體類的構造方法: productFactory.RegisterObjectCreator("PRODUCT_A", boost::factory<ConcreteProductA *>() ); 注意:這里用到了boost::factory,它可以將 new 表達式封裝成函數對象(function object),? 這也正式我們工廠的注冊方法所需要的參數。
后面我們調用對象工廠的MakeObject來生成我們期望的ConcreteProduct對象。 我們用一個字符串來標識要生成哪種類型的ConcreteProduct對象。同時我們將返回的對象指針保存在 shared_ptr中,從而實現對象的自動管理。 類型Product_ptr的定義為: typedef boost::shared_ptr<Product> Product_ptr;? 它是對Product接口的智能指針封裝。
最后,就是展示多態行為的時候了,我們調用不同ConcreteProduct對象的DoSomething來演示。運行效果如下:
?
?
限制說明:
1. 本文只是實現了帶有默認構造函數的對象工廠。 如果你愿意也可以實現帶有多個參數構造函數的對象工廠。
2. ObjectFactory 也可以實現為Singleton模式,根據個人需要吧,本文的重點不在這里。
本文轉自莫水千流博客園博客,原文鏈接:http://www.cnblogs.com/zhoug2020/p/5912281.html,如需轉載請自行聯系原作者
總結
- 上一篇: 实践 config drive - 每天
- 下一篇: 波形捕捉:(2)创建捕捉设备对象