通常,对象工厂通过调用
来创建类的实例auto world = ObjectFactory::instance()->create("MatrixTransform");
auto cube1 = ObjectFactory::instance()->create("Cube");
auto sphere = ObjectFactory::instance()->create("Sphere");
使用没有参数的已注册函数的映射,例如,类Node
是类MatrixTransform
,Cube
和Sphere
的基类:
// Map of registered factory functions
std::map<std::string, std::function<Node *(void)>> functionRegistry;
现在,我想注册带有有限数量参数(一个或两个)的重载构造函数,例如MatrixTransform(std::string objectName)
或MatrixTransform(std::string objectName, glm::mat4 matrixTransform)
,所以我不仅可以调用
auto world = ObjectFactory::instance()->create("MatrixTransform");
但也
auto world = ObjectFactory::instance()->create("MatrixTransform", "world");
甚至
auto world = ObjectFactory::instance()->create("MatrixTransform", "world", "glm::mat4())");
我知道可以在地图中存储具有不同签名的函数,这意味着具有不同参数和/或返回类型的函数,但是如何注册不仅具有不同签名而且具有相同名称的函数,例如上面重载的构造函数,假设映射中的键必须是唯一的,因此不能重复?如果需要,可以发布整个对象工厂代码。谢谢!
答案 0 :(得分:1)
想到了两种可能的解决方案。
我可以创建3个地图而不是一个:一个用于没有参数的函数,第二个用于具有一个参数的函数,第三个用于具有2个参数的函数。这样,我将有3个地图,每个地图都有具有相同签名的功能的唯一地图条目!
更简单的解决方案是保留初始地图并继续使用通用构造函数创建对象,然后使用setter设置其名称和矩阵变换参数。
嘿,他们真的说你要问一个问题才能找到答案!梦见代码。答案 1 :(得分:1)
如果您接受使用枚举类,则不必使用地图:
Fragment
重载,模板和标签调度可以在这里完成工作。
注意:该示例需要C ++ 14,但它是使用正确的返回类型而不是#include<utility>
#include<string>
enum class Type { MatrixTransform, Cube, Sphere };
template<Type>
struct tag {};
struct Factory {
template<Type T, typename... A>
static auto create(A&&... args) {
return create(tag<T>{}, std::forward<A>(args)...);
}
private:
static auto create(tag<Type::MatrixTransform>) {}
static auto create(tag<Type::MatrixTransform>, std::string) {}
static auto create(tag<Type::Cube>) {}
static auto create(tag<Type::Sphere>) {}
};
int main() {
Factory::create<Type::MatrixTransform>();
Factory::create<Type::MatrixTransform>("foo");
}
的问题,它也适用于C ++ 11。