在访问者模式中使用accept() [英] The use of an accept() in the Visitor pattern

查看:139
本文介绍了在访问者模式中使用accept()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究使用访客模式。我看到的一些示例建议在每个Element子类中使用accept(Visitor)函数。这个函数的想法只是让访问者访问包含多态类型的集合吗?在这段代码中,我使用一个访问者做两种类型的累积,它不需要accept()。

I am looking into using the Visitor pattern. Some of the examples I see suggest using an accept(Visitor) function in every Element subclass. Is the idea of that function just so that a visitor can visit a collection that contains polymorphic types? In this code, I use a visitor to do two types of accumulation, and it doesn't require accept().

#include <iostream>
#include <vector>

class IntItem
{
public:
  IntItem(const int a) : IntData(a){}

  int IntData;
};

class DoubleItem
{
public:
  DoubleItem(const double a) : DoubleData(a){}

  double DoubleData;
};

class Visitor
{
public:
  virtual void Visit(IntItem &item) = 0;
  virtual void Visit(DoubleItem &item) = 0;
};


class SumAccumulator : public Visitor
{
public:

  SumAccumulator() : Sum(0) {}
  void Visit(IntItem &item)
  {
    Sum += item.IntData;
  }

  void Visit(DoubleItem &item)
  {
    Sum += item.DoubleData;
  }

  double Sum;
};

class AverageAccumulator : public Visitor
{
public:

  AverageAccumulator() : Average(0), Counter(0) {}
  void Visit(IntItem &item)
  {
    Counter++;
    Average = (Counter - 1) * Average + item.IntData;
    Average /= Counter;
  }

  void Visit(DoubleItem &item)
  {
    Counter++;
    Average = (Counter - 1) * Average + item.DoubleData;
    Average /= Counter;
  }

  int Counter;
  double Average;
};

class IntCollection
{
public:
  void Visit(Visitor &visitor)
  {
    for(unsigned int i = 0; i < IntItems.size(); ++i)
      {
      visitor.Visit(IntItems[i]);
      }
  }

  void AddIntItem(const IntItem& item)
  {
    IntItems.push_back(item);
  }

private:
  std::vector<IntItem> IntItems;

};

class DoubleCollection
{
public:
  void Visit(Visitor &visitor)
  {
    for(unsigned int i = 0; i < DoubleItems.size(); ++i)
      {
      visitor.Visit(DoubleItems[i]);
      }
  }

  void AddDoubleItem(const DoubleItem& item)
  {
    DoubleItems.push_back(item);
  }

private:
  std::vector<DoubleItem> DoubleItems;
};

int main(int argc, char *argv[])
{
  /////// Ints ////////
  IntCollection intCollection;
  for(unsigned int i = 0; i < 4; ++i)
    {
    intCollection.AddIntItem(IntItem(i));
    }

  SumAccumulator intSumAccumulator;
  intCollection.Visit(intSumAccumulator);
  std::cout << "int sum: " << intSumAccumulator.Sum << std::endl;

  AverageAccumulator intAverageAccumulator;
  intCollection.Visit(intAverageAccumulator);
  std::cout << "int average: " << intAverageAccumulator.Average << std::endl;

  /////// Doubles ////////
  DoubleCollection doubleCollection;
  for(unsigned int i = 0; i < 4; ++i)
    {
    doubleCollection.AddDoubleItem(DoubleItem(static_cast<double>(i) + .1));
    }
  SumAccumulator doubleSumAccumulator;
  doubleCollection.Visit(doubleSumAccumulator);
  std::cout << "double sum: " << doubleSumAccumulator.Sum << std::endl;

  AverageAccumulator doubleAverageAccumulator;
  doubleCollection.Visit(doubleAverageAccumulator);
  std::cout << "double average: " << doubleAverageAccumulator.Average << std::endl;

  return 0;
}

在这段代码中,我使用accept(),唯一的区别是该容器可以在同一个容器中包含不同类型的对象:

In this code, I do use accept(), and the only difference is that the container can contain objects of varying types in the same container:

#include <iostream>
#include <string>
#include <vector>

class IntElement;
class DoubleElement;

class Visitor
{
public:
  virtual void visit(IntElement *e) = 0;
  virtual void visit(DoubleElement *e) = 0;
};

class Element
{
public:
  virtual void accept(class Visitor &v) = 0;
};

class IntElement: public Element
{
public:
  IntElement(int i) : IntData(i){}
  /*virtual*/void accept(Visitor &v)
  {
    v.visit(this);
  }

  int IntData;
};

class DoubleElement: public Element
{
public:
  DoubleElement(double d) : DoubleData(d){}
  /*virtual*/void accept(Visitor &v)
  {
    v.visit(this);
  }

  double DoubleData;
};

class SumVisitor: public Visitor
{
public:
  SumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }
  /*virtual*/void visit(DoubleElement *e)
  {
    Sum += e->DoubleData;
  }

  double Sum;
};

class AverageVisitor: public Visitor
{
public:
  AverageVisitor() : Counter(0) , Average(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Counter++;
    Average = (Counter - 1) * Average + e->IntData;
    Average /= Counter;
  }
  /*virtual*/void visit(DoubleElement *e)
  {
    Counter++;
    Average = (Counter - 1) * Average + e->DoubleData;
    Average /= Counter;
  }
  double Average;
  int Counter;
};

int main()
{
  std::vector<Element*> elements;
  elements.push_back(new IntElement(0));
  elements.push_back(new IntElement(1));
  elements.push_back(new DoubleElement(2));
  elements.push_back(new DoubleElement(3));

  SumVisitor sumVisitor;
  AverageVisitor averageVisitor;
  for (int i = 0; i < elements.size(); i++)
    {
    elements[i]->accept(sumVisitor);
    elements[i]->accept(averageVisitor);
    }
  std::cout << "sum: " << sumVisitor.Sum << std::endl;
  std::cout << "average: " << averageVisitor.Average << std::endl;
}

这个区别是否正确?也就是说,如果我只计划使用同类容器,我不需要实现accept函数?

Is this distinction correct? That is, if I only plan on having homogeneous containers I do not need to implement accept functions?

推荐答案


这个区别是否正确?也就是说,如果我只计划拥有
的均匀容器,我不需要实现accept函数?

Is this distinction correct? That is, if I only plan on having homogeneous containers I do not need to implement accept functions?

基本上,如果你有一个相对稳定的 Element 层次结构,新访问者衍生物。然后可以调用访问者,而无需调用者知道正在操作的元素的具体类型。

Basically, if you have a relatively stable Element hierarchy, it allows you to add new Visitor derivatives as necessary. The visitors can then be invoked without the invoker knowing the concrete type of the element being operated on.

这篇关于在访问者模式中使用accept()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆