您需要为您希望能够通过这种方式构建的每个类实例化工厂函数。下面的代码展示了如何做到这一点,而不必再发生静态成员和不能用手写了许多不同的功能:
#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