我正在试图找出解决以下问题的方法(剥离了实际代码的版本,抱歉明显的内存泄漏):
#include <iostream>
namespace A {
struct Product {
virtual void doSomething() const =0;
};
template<typename T>
struct SpecialProduct : public Product {
T t;
SpecialProduct(T t) : t(t) {};
virtual void doSomething() const { std::cout << "A: " << t << " does something\n"; }
};
struct Factory {
template<typename T>
Product* create(T t = T()) const { return new SpecialProduct<T>(t); }
};
}
namespace B {
struct Product {
virtual void doSomething() const =0;
};
template<typename T>
struct SpecialProduct : public Product {
T t;
SpecialProduct(T t) : t(t) {};
virtual void doSomething() const { std::cout << "B: " << t << " does something\n"; }
};
struct Factory {
template<typename T>
Product* create(T t = T()) const { return new SpecialProduct<T>(t); }
};
}
struct ProductType { };
template<typename T>
struct SpecialProductType : public ProductType {};
int main() {
// I have a factory of a known type
A::Factory f;
// standard procedure
A::Product* p = f.create<int>();
p->doSomething();
// I have a product type description from some source
ProductType* t = /* some source */ 0;
// How do i get a product instance of type t from f?
// A::Product* p = f. ???
}
我有一个模块的多个实现,在这种情况下在不同的命名空间内。工厂模式用于处理变体。每个模块提供(抽象)产品和专用通用版本。产品类型使用统一的类基础结构来表示,遵循相同的模式。
我的问题是:给定指向专用产品类型的指针,如何实现从给定工厂对象生成相应专用产品实例的函数?
非常感谢任何建议。
答案 0 :(得分:0)
在研究了几天之后,我想出了以下解决方案:
#include <iostream>
#include <functional>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
using namespace std;
struct ProductType {
type_index type;
ProductType(type_index type) : type(type) {}
};
template<typename T>
struct SpecialProductType : public ProductType {
SpecialProductType() : ProductType(typeid(T)) {}
};
template<typename Derived, typename _product_type>
struct FactoryBase {
typedef _product_type product_type;
map<type_index, function<product_type*()>> creators;
template<typename T>
void addProductType() {
creators[typeid(T)] = [&]()->product_type* {
static_cast<Derived*>(this)->template create<T>();
};
}
product_type* createForType(const ProductType& type) {
return creators[type.type]();
}
};
namespace A {
struct Product {
virtual void doSomething() const =0;
};
template<typename T>
struct SpecialProduct : public Product {
T t;
SpecialProduct(T t = T()) : t(t) {};
virtual void doSomething() const { std::cout << "A: " << typeid(T).name() << " does something\n"; }
};
struct Factory : public FactoryBase<Factory,Product> {
typedef Product product_type;
template<typename T>
Product* create() const {
std::cout << "A is creating a product of type " << typeid(T).name() << "\n";
return new SpecialProduct<T>();
}
};
}
namespace B {
struct Product {
virtual void doSomething() const =0;
};
template<typename T>
struct SpecialProduct : public Product {
T t;
SpecialProduct(T t = T()) : t(t) {};
virtual void doSomething() const { std::cout << "B: " << typeid(T).name() << " does something\n"; }
};
struct Factory : public FactoryBase<Factory,Product> {
typedef Product product_type;
template<typename T>
Product* create() const {
std::cout << "B is creating a product of type " << typeid(T).name() << "\n";
return new SpecialProduct<T>();
}
};
}
int main() {
// I have a factory of a known type
A::Factory f;
f.addProductType<float>();
f.addProductType<string>();
ProductType* tf = new SpecialProductType<float>();
ProductType* ts = new SpecialProductType<string>();
f.createForType(*tf)->doSomething();
f.createForType(*ts)->doSomething();
}
基本上我是根据要在FactoryBase类中创建的产品类型构建自己的动态调度程序表。关键是泛型类型,值是一个能够创建适当实例的仿函数。
所提出的解决方案的缺点是需要注册支持的类型列表 - 但这可以在不改变工厂代码或产品类型(开/关原则)的情况下完成。任何用户代码都可以动态扩展支持的产品类型列表。