我想要一个类,它根据我传递给它的字符串创建不同种类的对象。根据我的研究,这最能描述工厂设计模式。我成功地实现了它,但我遇到了一个设计问题:我不知道如何创建具有不同长度构造函数的对象。
让我们举个例子,一个叫做Pet的抽象父类。其中有 3 个 child :鱼、猫和狗。它们都从 Pet 继承了重量和颜色,因此它们的构造函数中也有。但是一条鱼可能需要一些鳍和一个关于它是否是咸水鱼的 bool 值。这是一个 4 参数构造函数。猫想要腿的数量。那是3个参数。这只狗可能有腿、品种以及他是否与其他狗玩得好等参数,共 5 个参数。
在 C++ 中,我知道没有任何反射,所以最常见的做法似乎是只声明一个字符串到函数指针的映射,其中函数指针指向一个看起来像这样的函数:
template<typename T> Pet* createObject(int weight, std::string color) {return new T(weight, color);}
同样,我不确定如何在调用中填充更多参数而不影响其他对象的构造函数的调用。
我可以想到两种解决方法:创建新函数以接受不同数量的参数,或者为超过一定大小的构造函数设置默认参数。
解决方法 1 似乎有点过分,具体取决于我有多少不同的参数大小。
解决方法 2 似乎忽略了构造函数的整个要点,因为我将在调用构造函数后被迫分配数据。
还有其他更好的解决方法吗?
最佳答案
您可以使用可变参数模板和完美转发。
template<typename T, typename... Args>
Pet* createObject(Args&&... args) {
return new T(std::forward<Args>(args)...);
}
但是,由于任何指针都可以转换为其基类,因此如果此函数返回 T*
可能会更好。此外,使用裸指针并不明智,因为您必须手动删除它们。最好使用shared_ptr
或 unique_ptr
.对于这些类,已经有类似的工厂方法:make_shared
和 make_unique
(后者仅在 C++14 中)。或者,如果您的编译器不支持 C++11,那么您可以使用 Boost 中的 shared_ptr
和 make_shared
.
当然,当您在编译时知道需要创建什么类型时,此解决方案就可以使用。如果你必须在运行时决定它,那么整个问题必须从不同的方向来考虑,就像你不知道你要创建什么类型,那么你就没有办法知道给他们什么参数,所有类型通用的参数除外。在这种情况下,您需要的是 abstract factory pattern .幸运的是,C++(至少从 C++11 开始)提供了一种无需创建大量类即可实现此模式的方法。例如,假设您必须创建从 Pet
派生的某个类的实例。宠物的实际种类、大小和其他属性在其他地方决定,而宠物的名称在创建时决定。然后,您需要一个这样的工厂:
typedef std::function<std::shared_ptr<Pet>(const std::string& name)> PetFactory;
在某些时候,您决定要创建一个Dog
(我将实际创建参数的含义留给您自己想象)。
PetFactory petFactory =
[](const std::string& name) {
return std::make_shared<Dog>(name, 12, "brown", 23.5);
}
当你真正创建它时,你只需要调用工厂:
std::shared_ptr<Pet> pet = petFactory("Pet Name");
关于c++ - 工厂设计模式如何处理不同长度的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31477785/