防止复合访问者重复

时间:2012-02-08 21:34:05

标签: c++ generics

我目前有两个访问者都正常工作。

#include <iostream>
#include <vector>

struct VisitorA
{
  void DoSomething(){}
};

struct VisitorB
{
  void DoSomething(){}
};

template <typename TVisitor>
static void RunAlgorithm(TVisitor& visitor);

int main()
{
  VisitorA visitorA;
  VisitorB visitorB;
  RunAlgorithm(visitorA);
  RunAlgorithm(visitorB);
}

template <typename TVisitor>
void RunAlgorithm(TVisitor& visitor)
{
  visitor.DoSomething();
}

现在我想在算法中应用两个访问者。我见过一个“复合”访问者,它存储了多个访问者并简单地将呼叫转发给每个访问者。要做到这一点,似乎我必须创建一个“ParentVisitor”类并从中派生出来,这样我才能将ParentVisitor *存储在容器中:

#include <iostream>
#include <vector>

struct VisitorParent
{
  void DoSomething(){}
};

struct VisitorA : public VisitorParent
{
  void DoSomething(){}
};

struct VisitorB : public VisitorParent
{
  void DoSomething(){}
};

struct VisitorComposite : public VisitorParent
{
  void DoSomething()
  {
    for(unsigned int i = 0; i < Visitors.size(); ++i)
      {
      Visitors[i]->DoSomething();
      }
  }
  std::vector<VisitorParent*> Visitors;
};

static void RunAlgorithm(VisitorParent& visitor);

int main()
{
//   VisitorA visitor;
//   RunAlgorithm(visitor);

  VisitorA visitorA;
  VisitorB visitorB;
  VisitorComposite visitorComposite;
  visitorComposite.Visitors.push_back(&visitorA);
  visitorComposite.Visitors.push_back(&visitorB);
  RunAlgorithm(visitorComposite);
}

void RunAlgorithm(VisitorParent& visitor)
{
  visitor.DoSomething();
}

这样做的问题是,如果访问者有一些重复的功能,它将执行两次。我想把重复的代码移到VisitorParent,但是我不知道如何说“只为其中一个访问者运行父代码,而对于重复的部分只运行其余的代码”。这似乎是“手动” - 是否有更好的机制来应用两个(或更多)访问者?

2 个答案:

答案 0 :(得分:0)

在我看来,除了抽象基础访问者类之外,您实际上总共需要四个具体访问者:

  1. 包含A和B中的常见操作的一个
  2. 包含A
  3. 特有的操作
  4. 包含B
  5. 特有的操作
  6. 一个可以通过抽象基类调用多个其他访问者的合成器
  7. 然后原始访问者A的角色通过与uniqueA组成共同来处理,访问者B的角色通过与uniqueB组成共同来处理,并且组合操作通过组成common,uniqueA和uniqueB来处理。

    重复数据删除可以在合成器的工厂函数中完成,但您可能不希望在合成器类中“烘焙”重复数据删除,以保持更多的灵活性。

答案 1 :(得分:0)

使用访问者模式,如果你运行它,你真的不希望任何“破坏”。所以当你运行两次它应该可以工作。 是否你运行两次是一个比访问者更高级别的关注,所以它不应该影响访问者的设计。

因此,手册在这种情况下可能很好。

复合材料的作用可能应该是一个控制器。它可能知道,如果一个访问者成功,另一个访问者也不适合运行。向访问者添加返回值将为复合提供控制运行所需的反馈。控制器关注的是运行什么,访客保持愚蠢。