4

我花了一整天的时间研究这个话题,所以我带着这个话题来找你的只是一些零散的知识。请允许我描述一下我正在尝试完成的工作,也许您可​​以提出解决当前问题的方法,或者另一种完全解决问题的方法。

我试图模仿与XAML文件在WPF中的工作方式相关的内容,您实际上是在从 XML 定义中实例化对象树。如果这不正确,请告知。这个问题与WPFC#或任何托管的东西无关- 我只提到它是因为它是一个类似的概念。

因此,我已经创建了一个XML解析器类,并基于ObjectNode对象生成了一个节点树。ObjectNode对象拥有一个名为type的字符串值,并且它们有一个std::vectorObjectNode对象。

下一步是根据ObjectNode树中的数据实例化对象树。需要此中间ObjectNode树,因为同一ObjectNode树可能会被实例化多次或根据需要延迟。正在创建的对象树使得树中的节点是公共基类的后代,现在我们可以将其称为MyBase。叶节点可以是任何类型,不一定从MyBase派生。

为了使这更具挑战性,我不知道树中可能涉及哪些类型的对象,因此我需要允许向工厂注册新类型。

我知道boost的工厂。他们的文档在此页面上有一个有趣的小设计段落:

o 我们可能想要一个工厂,它接受一些转发给构造函数的参数,
o 我们可能想要使用智能指针,
o 我们可能想要几个成员函数来创建不同类型的对象,
o 我们可能不一定需要多态基对象的类,
o 正如我们将看到的,我们根本不需要工厂基类,
o 我们可能只想调用构造函数 - 没有 #new# 在堆栈上创建对象,
最后我们可能想要使用自定义的内存管理。

我可能没有正确理解这一切,但这似乎表明我正在尝试做的事情可以通过 boost 的工厂来完成。但是我找到的所有示例似乎都描述了所有对象都派生自基本类型的工厂。

对此的任何指导将不胜感激。

谢谢你的时间!

4

4 回答 4

2

为工厂方法定义 typedef,例如:

typedef void* (*FactoryMethod)(const vector<string>& parameters);

换句话说,每个工厂方法都返回一个指向任何东西的指针(指向 void 的指针),并将字符串的 const 向量作为参数。

注册数据如下所示:

std::map<string, FactoryMethod> globalFactoryMethods;

...其中键是类型string,值是指向相应工厂方法的指针。当您拥有具有新工厂方法的新类型时,通过将其添加到映射(在运行时)来“注册”它。

使用注册的工厂方法的构造可能如下所示(伪代码):

foreach (Node node in nodes)
{
  string type = node.type;
  FactoryMethod factoryMethod = globalFactoryMethods[type];
  void* constructedLeaf = (*factoryMethod)(node.nParameters, node.pParameters);
  //do something here with constructed leaf
}

叶节点可以是任何类型,不一定从 MyBase 派生。

这是 C++ 中的一个问题:如果您不知道它们是什么,那么您将如何删除它们?

C#(与 C++ 不同)可以在不知道它们是什么的情况下删除它们,或者更确切地说它不需要删除它们:因为它是托管内存,并且一切都是System.Object.

于 2010-05-23T23:57:17.403 回答
1

你描述了你的问题是一件非常好的事情:)

让工厂能够创建任何类型的想法当然非常诱人,但它既复杂又不必要。我理解void*不幸的是它的吸引力并不像看起来那么迷人。对于这样的野兽,您唯一能做的就是将其转换为正确的指针......这需要在编译时知道类型是什么!

假设我有一个std::vector<void*>,我要求你打印出这个向量的内容,你要做什么?

强迫人们让他们创建的类继承自您设计的基类是完全可以接受的,该基类的目的是便于工厂处理。

struct Object: boost::noncopyable
{
  virtual Object* clone() const = 0;
  virtual ~Object() {}
};

与要求从此类继承相比,这确实是一个非常小的约束。作为交换,您获得了虚拟析构函数,并确保可以多态地复制类(感谢clone成员函数)以避免对象切片问题。

我认为您应该阅读一些设计模式:

  • 原型被广泛用于实现工厂,尽管它不是唯一的方法
  • Factory,你似乎已经知道了,也许这AbstractFactory对你也有帮助
  • 复合是处理对象树的必要条件
  • Visitor确实有助于定义一种向前兼容的操作方式Composite
于 2010-05-24T11:30:40.317 回答
0

我无法真正理解您的问题,但从主题来看,我认为您正在尝试创建任意注册对象,也许您可​​以查看设计模式“原型”
点击此处查看全能维基

于 2010-05-24T01:09:00.880 回答
0

如果我认为我理解正确,也许是这样的:

void register(string constructor, void*(*method)(...)); // put in map

template<class T>
T* new_(string subclass, ...) {
  return static_cast<T*>(constructors_[subclass](...));
}
于 2010-05-24T00:11:17.750 回答