vam*_*msi 48 design-patterns double-dispatch visitor
我正在阅读有关访客模式的内容,它看起来像Double Dispatch.两者之间有什么区别吗?这两个术语是否意思相同.
Emi*_*lia 41
它们来自不同的概念,在某些语言中,双重调度本身不受支持,导致访问者模式作为连接两个(或更多)单个调度的方式,以便具有多调度代理.
多次发送的想法 - 基本上 - 允许像这样的呼叫
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*);
Run Code Online (Sandbox Code Playgroud)
所以,在打电话时
fn(pa, pb)
Run Code Online (Sandbox Code Playgroud)
呼叫重定向到实际相匹配的倍率运行时类型两者的pa和pb.(您可以将此概括为任意数量的参数)
在C++,C#,Java等语言中,这种机制不存在,运行时类型调度基本上只使用一个参数(只是一个参数,通过使函数本身成为类的成员而在函数中隐含:
换句话说,伪代码
void fn(virtual base_a*, base_b*)
Run Code Online (Sandbox Code Playgroud)
成为(真正的C++)
class base_a
{
public:
virtual void fn(base_b*);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这里没有更多的virtual前面base_b,从现在开始是静态的.像这样的电话
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:
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); }
...
};
Run Code Online (Sandbox Code Playgroud)
现在,pa->fn(pb)如果pa指向derived_a1和pb指向derived_b1,则调用最终会转到derived_a1::on_visit(derived_b1*).
Naw*_*waz 13
访问者模式是实现双重调度行为的一种解决方案.还可以有其他几种解决方案.术语双重调度本身并没有给出解决方案的任何想法,实际上它是一个问题,其解决方案由访问者模式提供.
在C#(4.0)中,可以使用dynamic关键字来实现双重调度,在这种情况下,不需要访问者模式.这是我使用关键字的双重调度问题的解决方案dynamic:
动态调度通常是指基于运行时信息调度到方法的概念.大多数OO系统(如在Java/C#/ C++中)通常通过virtual方法实现动态调度(所有方法是否都是虚拟的,取决于语言); 这限制了它们根据单个方法参数(隐式对象引用)进行分派.
通常,您可能希望根据任意数量的元素进行调度.例如,Double Dispatch是根据方法的两个参数分派的要求/能力.
另一方面,访客模式通常是Multi Dispatch 的实现,因此特别是在这样的OO系统中是Double Dispatch.
双重调度是一个技术问题,根据语言的不同,可以采用不同的方式来解决——有些语言直接支持双重调度。访问者模式是一种可用于解决不同问题的模式。就 C++ 而言,它是用于双重分派的最常见(但不是唯一)的解决方案,但它并不是专门用于此目的,即使在支持双重分派的语言中,它也很有用。