问题描述
我正在阅读有关访客模式的信息,并且看起来像双重调度.两者之间是否有任何区别. 做两个术语意味着同一件事.
参考: http://www.vincehuston.org/dp/dp/dp/visitor.html
推荐答案
在简称
中它们来自不同的概念化,这些概念化在某些语言中不受本地支持的方式,导致访问者模式作为连接两个(或更多)单个调度的一种方式,以便具有多dispatch替代.<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
在长
中多次调度的想法是 - 本质上是 - 允许像
这样的呼叫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*); }
请注意,base_b的前面不再有virtual,从现在开始是静态的. 像
这样的电话pa->fn(pb)如果pa指向derived_a2和pb到derived_b1的pa将被派遣到 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: 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); } ... };
现在,如果pa指向derived_a1和pb derived_b1,pa->fn(pb)之类的调用最终将转到derived_a1::on_visit(derived_b1*).
其他推荐答案
访问者模式是一个解决方案,它实现了双重调度的行为.也可以还有其他几种解决方案.术语 double dispatch 本身没有任何解决方案的想法,实际上是一个问题,其解决方案由访问者模式提供.
.在C#(4.0)中,可以使用dynamic关键字来实现双重调度,在这种情况下,不需要访问者模式.这是我使用dynamic关键字的 double-dispatch问题的解决方案:
其他推荐答案
动态调度通常是指根据运行时信息的方法概念.大多数OO系统(如Java/C#/C ++中)通常通过virtual方法实现动态调度(是否所有方法都是虚拟依赖于语言的);这限制了他们根据单个方法参数(隐式对象参考)进行分发.
通常,您可能需要根据任意数量的元素进行分发.例如,双调格是根据方法的两个参数进行分发的要求/能力.
另一方面,访问者模式是的实现一般的多次调度,因此在此类OO系统中尤其是双重调度.
问题描述
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*).
其他推荐答案
Visitor pattern is one solution which implements the behaviour of double dispatch. There can be several other solutions as well. The term double dispatch itself doesn't give any idea of solution, in fact it is a problem whose solution is provided by visitor pattern.
In C# (4.0), one could use dynamic keyword to implement double dispatch, in which case visitor pattern is not required. Here is my solution to double-dispatch problem using dynamic keyword:
其他推荐答案
Dynamic Dispatch refers to the concept of dispatching to a method based on runtime information, in general. Most OO systems (as in Java/C#/C++) usually implement dynamic dispatch via virtual methods (whether or not all methods are virtual depend from the language); this restricts them to dispatch according to a single method argument (the implicit object reference).
In general you could want to dispatch according to an arbitrary number of elements. Double Dispatch, for example, is the requirement/ability to dispatch according to two arguments of the method.
On the other hand, the Visitor Pattern is an implementation of Multi Dispatch in general and thus Double Dispatch in particular in such OO systems.