c++ - 自定义对象工厂

标签 c++ c++11 factory factory-pattern

我的图书馆使用对象工厂技术来创建具有特定用途的“节点”。默认情况下,这些节点会完成它们的工作,但非常基础。我想让我的库的用户能够创建所提供的“节点”类的子类来定义他们自己的功能,同时保持节点的基本功能不变。 下面是一些示例代码来演示我的问题:

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)。

编辑:

表述问题的更简洁的方式如下:如果用户定义了一个子类而不是我的默认基类,我如何让用户告诉工厂创建他们的子类的实例?我想再次感谢大家花时间和精力回答这个问题。

最佳答案

我认为这里的问题是结合以下两个要求:

  1. 您想使用非常简单的函数 void CreateNode(int) 来创建任何节点。
  2. 您希望用户能够创建从 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/

相关文章:

c++ - SFINAE:如果不带参数调用,则会出现不明确的重载

c++ - 我所在的对象的哪个迭代

c++ - 具有资源管理器的智能指针,让对象 "borrow"资源

c++ - 断开连接后重新连接 boost beast (asio) websocket 和 http 连接时出错

c++ - std::enable_if 跨编译器的不同行为(取决于外部类模板参数)

c++ - 如何使用迭代器遍历 pair<int,pair<int,int>> 形式的映射

java - 将时间对象持久化为实体而不是值类型?

c++ - 扩展枚举

c++ - 阻塞 unix 域套接字的问题

PHPUnit Laravel InvalidArgumentException : Unable to locate factory with name [default] [App\User]