您需要爲您希望能夠通過這種方式構建的每個類實例化工廠函數。下面的代碼展示瞭如何做到這一點,而不必再發生靜態成員和不能用手寫了許多不同的功能:
#include <iostream>
#include <map>
#include <functional>
#include <string>
#include <memory>
struct Parent{
Parent(std::string){}
};
struct Child1 : public Parent{
Child1(std::string d) : Parent(d){
std::cout << "Child1 constructor: " << d << std::endl;
}
};
struct Child2 : public Parent{
Child2(std::string d) : Parent(d){
std::cout << "Child2 constructor: " << d << std::endl;
}
};
template <typename Product, typename Return, typename Parameter>
Return factory(const Parameter& a){
return Return(new Product(a));
}
std::map<std::string, std::function<Parent*(std::string)> > mrp;
std::map<std::string, std::function<std::shared_ptr<Parent>(std::string)> > msp;
int main(){
mrp["Child1"] = &factory<Child1, Parent*, std::string>;
mrp["Child2"] = &factory<Child2, Parent*, std::string>;
Parent* a = mrp["Child1"]("one");
delete a;
std::unique_ptr<Parent> b(mrp["Child2"]("two"));
msp["Child1"] = &factory<Child1, std::shared_ptr<Parent>, std::string>;
msp["Child2"] = &factory<Child2, std::shared_ptr<Parent>, std::string>;
msp["Child1"]("one");
msp["Child2"]("two");
}
試試這個代碼here。 此外,你可以看到,這種方法可以「配置」使用std :: shared_ptr的,裸指針,......和不同所有制semanthics,注意行:
std::unique_ptr<Parent> b(mrp["Child2"]("two"));
然而,任何變化你在問題中簡要描述的是,它的一個變種!你所要做的是一個抽象工廠,「標準」實現完全依賴於爲你想要構建的每個類創建一個工廠函數。正如我所說的,它不需要是類的靜態成員,它可以是非成員的非友元函數,但這並沒有太大的改變(除了更好的封裝,以及構造函數的存在公衆或工廠成爲朋友,這在某種程度上打破封裝)。
對象工廠在loki中以非常優雅的方式實現。請參閱Modern C++(Alexandrescu),詳細討論設計模式本身以及Loki給出的實現。
至於你的編輯:在洛基註冊是甜而簡單的(引自書):
// Implementation module for class Line
// Create an anonymous namespace
// to make the function invisible from other modules
namespace
{
Shape* CreateLine()
{
return new Line;
}
// The ID of class Line
const int LINE = 1;
// Assume TheShapeFactory is a singleton factory
// (see Chapter 6)
const bool registered =
TheShapeFactory::Instance().RegisterShape(
LINE, CreateLine);
}
您可以通過創建一個非靜態函數來避免創建一個靜態函數。 – juanchopanza
@juabchopanza:呵?這是一個分配器函數,所以它不應該在類實例上工作(與克隆函數相反)...主題 – galinette
正好,我不是說它應該在類實例上工作。 – juanchopanza