我的图书馆使用对象工厂技术来创建具有特定用途的“节点”。默认情况下,这些节点会完成它们的工作,但非常基础。我想让我的库的用户能够创建所提供的“节点”类的子类来定义他们自己的功能,同时保持节点的基本功能不变。 下面是一些示例代码来演示我的问题:
class Node
{
int SomeValue;
public:
Node(int Value)
{
SomeValue = Value;
}
~Node()
{
// Cleanup the node
}
};
class NodeFactory
{
std::vector<Node*> Nodes;
public:
void CreateNode(int Value)
{
Nodes.push_back(new Node(Value));
}
};
这展示了基本的对象工厂技术,现在是我的问题。 我可以向“NodeFactory”添加一个函数,例如“void SetType()”,并能够传入“Node”的子类,这反过来会在“CreateNode”函数期间创建该子类吗?
非常感谢您抽出宝贵时间。
编辑:
“void CreateNode()”的用法是从最终用户那里抽象出来的,因此我对“void RegisterType()”函数感到好奇,用户可以在该函数中注册他们的子类以供工厂创建,而不是基础-我提供的类(class)。
编辑:
表述问题的更简洁的方式如下:如果用户定义了一个子类而不是我的默认基类,我如何让用户告诉工厂创建他们的子类的实例?我想再次感谢大家花时间和精力回答这个问题。
最佳答案
我认为这里的问题是结合以下两个要求:
- 您想使用非常简单的函数 void CreateNode(int) 来创建任何节点。
- 您希望用户能够创建从 Node 派生的新节点并使用您的工厂来创建它们。
现在我建议的是类似于 R Sahu 的东西,但是没有像他那样严格遵循工厂模式。
您可以通过要求您的用户将一个小的 Creator 对象传递给您的工厂来获得您寻求的功能。 (请注意,这有点偏离经典的工厂模式。因为您基本上使用创建者类将 NodeFactory 变成了委托(delegate)者。)
class NodeCreator {
public:
virtual Node* create(int) = 0;
virtual ~NodeCreator() = default;
};
class DefaultNodeCreator : public NodeCreator {
public:
virtual Node* create(int value) {
return new Node(value);
}
};
现在我作为用户将创建我自己的节点:
class MyNode : public Node {
private:
int otherValue;
public:
MyNode(int nodeValue, int otherValue )
: Node(nodeValue), otherValue(otherValue)
{}
// Implement other functionality...
};
class MyNodeCreator : public NodeCreator {
private:
// I added otherNodeValue to show that Creators can have a state.
int otherNodeValue;
public:
MyNodeCreator(int otherNodeValue ) : otherNodeValue(otherNodeValue) {}
virtual Node* create(int value) {
return new MyNode(value, otherNodeValue);
}
};
现在终于在您的工厂类中,您需要像这样设置它:
class NodeFactory
{
std::vector<Node*> Nodes;
std::unique_ptr<NodeCreator> activeCreator;
public:
NodeFactory() {
setNodeCreator(nullptr);
}
void createNode(int Value)
{
Nodes.push_back( activeCreator->create(Value) );
}
void setNodeCreator( std::unique_ptr<NodeCreator> creator ) {
if (creator == nullptr) {
activeCreator.reset( new DefaultNodeCreator() );
else {
activeCreator.reset(creator);
}
}
};
从 main 使用它:
int main() {
NodeFactory nf;
nf.createNode(1); // Creating Node(1)
nf.createNode(2); // Creating Node(2)
nf.setCreator( new MyNodeCreator(5) );
// Any nodes created now will be of type MyNode
// with otherNodeValue == 5.
nf.createNode(2); // Creating MyNode(2, 5)
nf.createNode(3); // Creating MyNode(3, 5)
}
最后一点:
如果您打算让您的用户实现 Node 的子类并将它们与上面所示的多态性一起使用,那么将 Node 的析构函数声明为虚拟的很重要。您无法保证您的用户不会在他们的子类中使用动态分配,因此您有责任确保调用他们的析构函数。
关于c++ - 自定义对象工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24216128/