Итерационная иерархия узлов - Visitor и Composite? - PullRequest
8 голосов
/ 12 февраля 2009

Давайте представим, что у меня есть коллекция узлов, которые я использую для своего класса Renderer позже. Затем у меня есть класс Visitor, который может посещать узел или целую коллекцию. Это просто, потому что моя коллекция узлов - это просто оболочка для std :: list с несколькими дополнительными методами.

Проблема в том, что я хотел бы иметь древовидную структуру для узлов (вместо простого списка), чтобы у узла мог быть родитель и n детей. Это было бы удобно, так как я хотел бы иметь возможность передать моему Renderer узел и отобразить все «ниже» этого узла. Ответ, вероятно, является составным.

Как я могу использовать вместе Visitor и Composite? Я читал, что это часто хорошая комбинация, но мои реализации выглядят довольно плохо ... Я скучаю по чему-то.

Ответы [ 3 ]

5 голосов
/ 12 февраля 2009

У меня что-то очень похожее реализовано для нашей системы. Мне нужен был способ составить иерархию геометрических объектов и отобразить их в объеме. Я использовал составной шаблон для составления моего описания (корнем был Node, а потом производным потомком был CompositeNode (список узлов).

В CompositeNode есть метод accept (), который принимает посетителя (Visitor), а затем внутри accept () вы делаете visitor-> visit (this).

Таким образом, ваша иерархия посетителей имеет базовый класс как NodeVisitor и производные посетители, такие как RenderVisitor (отображает объекты), ReportVisitor (помещает информацию об узле в текст). Ваш базовый класс должен принимать как базовые, так и специализированные типы узлов.

Так что да, комбо работает, и у меня есть рабочий код, но я согласен, что дизайн требует больше усилий, чем то, что вы читали бы онлайн (пример Wiki или игрушка).

Надеюсь, это поможет

3 голосов
/ 12 февраля 2009

Вот простой пример:

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);
    }
  }
};
0 голосов
/ 04 апреля 2013

Если вы хотите, чтобы ваш посетитель также знал структуру дерева (например, глубину, которую он посещает, или путь от корня дерева), вы можете рассмотреть использование иерархического шаблона посетителя. Это описано довольно долго на c2.com wiki

Также показано, как пропустить «неинтересную» ветку.

...