首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问者模式解释

访问者模式解释
EN

Stack Overflow用户
提问于 2012-04-12 08:58:54
回答 2查看 21.4K关注 0票数 26

因此,我已经阅读了关于访问者模式的所有文档,但我仍然非常困惑。我举了另一个问题的例子,有人能帮我理解一下吗?例如,我们什么时候使用访问者设计模式?我想我可能已经理解了其中的一些,但我就是看不到更大的图景。我怎么知道我什么时候可以使用它?

代码语言:javascript
复制
class equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor) = 0;
}

class floppyDisk : public equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor);
}

class processor : public equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor);
}

class computer : public equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor);
}

class equipmentVisitor
{
  virtual void visitFloppyDisk(floppyDisk* );
  virtual void visitProcessor(processor* );
  virtual void visitComputer(computer* );
}

// Some additional classes inheriting from equipmentVisitor would be here

equipmentVisited* visited;
equipmentVisitor* visitor;

// Here you initialise visited and visitor in any convenient way

visited->accept(visitor);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-12 09:10:12

访问者模式用于实现。简而言之,这意味着执行的代码依赖于两个对象的运行时类型。

当您调用常规虚函数时,它是单个分派:执行的代码段取决于单个对象的运行时类型,即您要调用的虚方法。

对于访问者模式,被调用的方法最终取决于两个对象的类型-实现equipmentVisitor的对象的类型,以及调用accept的对象的类型(即equipmentVisited子类)。

在C++中还有其他实现双重分派的方法。Scott Meyer的"More Effective C++"的第31项深入讨论了这个主题。

票数 36
EN

Stack Overflow用户

发布于 2014-02-01 12:21:43

我认为pattern Visitor的名字是非常不幸的。而不是访问者,我会说Functor或Operator,而不是'apply‘,我会说’apply‘。

我对访问者模式的理解如下:

在模板元编程(STL/BOOST) (编译时绑定)中,您可以通过函数对象(Functors)实现(正交设计)操作与结构的分离。例如,在

代码语言:javascript
复制
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

comp是一个函数器/运算符,以一种非常通用的方式表示‘小于’操作,所以你不需要有很多排序函数的变体:

对于访问者模式,您希望实现类似的东西,但在运行时(后期)绑定的情况下:

你想简化A的接口,你想为将来的扩展保留可能性(使用A的新操作),你想在这些扩展的情况下实现A的接口的稳定性。

来自最初的'fat‘类:

代码语言:javascript
复制
class A
{ 
  public:
    virtual void function_or_operation_1();//this can be implemented in terms of public interface of the other functions
    virtual void function_or_operation_2();
    //..etc

    virtual void function_or_operation_N();
  public:
    //stable public interface, some functions of procedures

  private:
  //....
}

您可以从公共接口中删除尽可能多的函数(只要它们可以在同一公共接口的非提取函数中实现),并将操作表示为函数对象或来自新函数层次结构的对象:

您可以通过使用forward声明的Functor_or_Operator的非常通用的接口来减少基类A中的函数数量:

代码语言:javascript
复制
 class Functor_or_Operator;
 class A
 {
   public:
     virtual void apply(Functor_or_Operator*);//some generic function operates on this objects from A hierarchy 
   //..etc
   public:
     //stable public interface, some functions

   private: 
     //....
 }

//现在您在A层次结构(A,B,C)中有N(=3)个类,并且由Functor_or_Operator层次结构中的类表示的M个操作或函数,您需要实现来自Functor_or_Operator的每个操作如何在A层次结构中的每个类上工作的N*M个定义。最重要的是,您可以在不更改类“A”的接口的情况下完成此操作。当引入新的操作或函数处理A层次结构的对象时,类'A‘的声明在新添加的情况下变得非常稳定,或者在A层次结构中有新的派生类的情况下。在添加的情况下,A的稳定性(不更改A)对于避免在许多地方包含A头的软件进行昂贵的(有时是不可能的)重新编译非常重要。

对于A层次结构中的每个新类,您扩展了基类Functor_or_Operator的定义,添加了新的实现文件,但您永远不需要触及基类A的头部(通常是接口或抽象类)。

代码语言:javascript
复制
  class Functor_or_Operator 
  {
    virtual void apply(A*)=0;
    virtual void apply(B*)=0;
    virtual void apply(C*)=0;
  }

  void A::apply(Functor_or_Operator* f) 
  { f->apply(this);} //you need this only if A is not abstract (it is instantiable)

  class B:public A
  {
    public:
     void apply(Functor_or_Operator* f) { f->apply(this);} //dynamic dispatch , you call polymhorphic Functor f on this object
     //..the rest of B implementation.
  }

  class C:public A
  {
    public:
     void apply(Functor_or_Operator* f) { f->apply(this);} //dynamic dispatch , you call polymorfic Functor f on this object
    //..the rest of C implementation.
  }

  class Functor_or_Operator_1:public Functor_or_Operator
  {
     public:
        //implementations of application of a function represented by Functor_or_Operator_1 on each A,B,C
        void apply(A*) {}//( only if A is instantiable,not an abstract class)
        void apply(B*) {}
        void apply(C*) {}
  }

  class Functor_or_Operator_2:public Functor_or_Operator
  {
    public:
      //implementations of application of a function represented by Functor_or_Operator_2 on each A,B,C
       void apply(A*) {}//( only if A is instantiable,not an abstract class)
       void apply(B*) {}
       void apply(C*) {}
  }
票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10116057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档