8

假设我有一个节点集合,稍后用于我的 Renderer 类。然后我有一个可以访问节点或整个集合的访问者类。这很简单,因为我的节点集合只是 std::list 的包装器,几乎没有额外的方法。

问题是我想要一个树状结构的节点(而不是简单的列表),所以一个节点可以有一个父节点和 n 个子节点。这会很方便,因为我希望能够将一个节点传递给我的渲染器并渲染该节点“下方”的所有内容。答案可能是复合。

如何同时使用访客和复合?我读过它通常是一个很好的组合,但我的实现看起来很糟糕......我错过了某事。

4

3 回答 3

5

我为我们的系统实现了一些非常相似的东西。我想要一种方法来组合几何对象的层次结构并将它们渲染到体积中。我使用复合模式来组成我的描述(根是节点,然后派生的子节点是复合节点(节点列表)。

CompositeNode 有方法 accept() 接受访问者 (Visitor),然后在 accept() 中执行访问者->访问 (this)。

因此,您的访问者层次结构具有作为 NodeVisitor 的基类和派生访问者,如 RenderVisitor(呈现对象)、ReportVisitor(将节点信息转储到文本中)。您的基类需要同时接受基本节点类型和专用节点类型。

所以是的,组合有效,我有工作代码,但我同意设计比你在网上阅读的内容(维基或玩具示例)需要更多的努力。

希望这可以帮助

于 2009-02-11T21:55:56.017 回答
3

这是一个简单的例子:

struct NodeVisitor;

struct Node
{
  virtual ~Node() {}
  virtual void accept(NodeVisitor &v);
};

struct CompositeNode : public Node
{
  virtual void accept(NodeVisitor &v);
  std::list<NodePtr> nodes_;
};

struct NodeVisitor
{
  virtual ~NodeVisitor() {}
  virtual void visit(Node &n) = 0;
  virtual void visit(CompositeNode &cn)
  {
    for(std::list<NodePtr>::iterator it = cn.nodes_.begin(), end = cn.nodes_.end(); it != end; ++it)
    {
      (*it)->accept(*this);
    }
  }
};
于 2009-02-11T23:31:37.097 回答
1

如果您希望您的访问者也知道树的结构(例如,它正在访问的深度或从树根开始的路径),您可以考虑使用分层访问者模式。这在c2.com wiki上的描述有些冗长

它还展示了如何跳过“无趣”的分支。

于 2013-04-04T15:18:01.373 回答