访客模式与双发 [英] Difference betwen Visitor pattern & Double Dispatch

查看:147
本文介绍了访客模式与双发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读关于访客模式,它看起来像双重派对一样。两者之间有什么区别吗?
这两个术语意思相同。



参考: http://www.vincehuston.org/dp/visitor.html

解决方案

简而言之, h2>

他们来自于不同的概念化,在某些语言中,双调度不是本机支持的,导致访问者模式作为将两个(或多个)单个调度连接起来的一种方式订单要有一个多调度代理。



在长的



多个调度的想法是 - 允许像



void fn(virtual base_a *,virtual base_b *); (注意:不作为类成员:这不是C ++!)



可以被覆盖为

  void fn(virtual derived_a1 *,virtual derived_b1 *); 
void fn(virtual derived_a2 *,virtual derived_b1 *);
void fn(virtual derived_a1 *,virtual derived_b2 *);
void fn(virtual derived_a2 *,virtual derived_b2 *);

这样,当调用

  fn(pa,pb)

该呼叫被重定向到覆盖它们与 pa pb 中的实际运行时类型相匹配。 (您可以将其推广到任何数量的参数)



在C ++,C#,Java等语言中,此机制不存在,运行时类型调度基本上只能使用一个参数(这只是一个,通过使函数本身成为类的成员,在函数中被隐含:



换句话说,伪代码

  void fn(virtual base_a *,base_b *)

成为(真正的C ++)

  class base_a 
{
public:
virtual void fn(base_b *);
}

请注意,在这里在$ code> base_b 之前没有更多的 virtual ,从现在开始就是静态的

pa-> fn(pb)如果pa指向derived_a2,pb到derived_b1将被分派到
derived_a2 :: fn(base_b *),无论是否存在derived_a2 :: fn(derived_b1 *):该对象指向的对象的运行时类型pb不被考虑。



访问者模式的想法是调用调用(最终返回)另一个虚拟调度的对象的虚拟调度:

  class base_a 
{
public:
virtual void fn(base_b *)= 0 ;
virtual void on_visit(derived_b1 *)= 0;
virtual void on_visit(derived_b2 *)= 0;
};

class base_b
{
public:
虚拟void on_call(derived_a1 *)= 0;
virtual void on_call(derived_a2 *)= 0;
};

//转发声明,允许指针在其他decls中自由使用。
class derived_a1;
class derived_b1;


class derived_a1:public base_a
{
public:
virtual void fn(base_b * pb){pb-> on_call(this); }
virtual void on_visit(derived_b1 * p1){/ *有用的东西* /}
...
};

class derived_b1:public base_b
{
public:
virtual void on_call(derived_a1 * pa1){pa1-> on_visit(this); }
...
};

现在,像 pa-> fn(pb),如果pa指向derived_a1和pb到derived_b1,将最终转到 derived_a1 :: on_visit(derived_b1 *)


I am reading about visitor pattern, and it appears the same like Double Dispatch. Is there any difference between the two. Do the two terms means the same thing.

reference: http://www.vincehuston.org/dp/visitor.html

解决方案

In short

they come from to different conceptualizations that, in some languages where double dispatch is not natively supported, lead to the visitor pattern as a way to concatenate two (or more) single dispatch in order to have a multi-dispatch surrogate.

In long

The idea of multiple dispatch is - essentially - allow a call like

void fn(virtual base_a*, virtual base_b*); (note: not as a class member: this is NOT C++! )

that can be overridden as

void fn(virtual derived_a1*, virtual derived_b1*);
void fn(virtual derived_a2*, virtual derived_b1*);
void fn(virtual derived_a1*, virtual derived_b2*);
void fn(virtual derived_a2*, virtual derived_b2*);

so that, when calling

fn(pa, pb)

the call is redirected to the override that matches the actual runtime type of both pa and pb. (You can generalize this to whatever number of parameters)

In language like C++, C#, Java, this mechanism does not exist and runtime type dispatching basically works with just one parameter (that, being just one, is made implicit in the function by making the function itself member of the class:

in other words, the pseudocode

void fn(virtual base_a*, base_b*) 

becomes the (real C++)

class base_a
{
public:
    virtual void fn(base_b*);
}

Note that here there is no more virtual in front of base_b, that from now is static. A call like

pa->fn(pb) if pa points to a derived_a2 and pb to a derived_b1 will be dispatched to derived_a2::fn(base_b*), no matter if there is a derived_a2::fn(derived_b1*) in there: the run-time type of the object pointed by pb is not taken into account.

The idea of the visitor patter is that you call the virtual dispatch of an object that calls (eventually back) the virtual dispatch of another:

class base_a
{
public:
   virtual void fn(base_b*)=0;
   virtual void on_visit(derived_b1*)=0;
   virtual void on_visit(derived_b2*)=0;
};

class base_b
{
public:
   virtual void on_call(derived_a1*)=0;
   virtual void on_call(derived_a2*)=0;
};

//forward declarations, to allow pointers free use in other decls.
class derived_a1;
class derived_b1;


class derived_a1: public base_a
{
public:
   virtual void fn(base_b* pb) { pb->on_call(this); }
   virtual void on_visit(derived_b1* p1) { /* useful stuff */ }
   ...
};

class derived_b1: public base_b
{
public:
  virtual void on_call(derived_a1* pa1) { pa1->on_visit(this); }
  ... 
};

now, a call like pa->fn(pb), if pa points to derived_a1 and pb to derived_b1, will finally go to derived_a1::on_visit(derived_b1*).

这篇关于访客模式与双发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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