我正在阅读访客模式,它看起来像Double Dispatch。两者之间有什么区别吗? 这两个术语是否意思相同。
答案 0 :(得分:41)
它们来自不同的概念,在某些语言中,双重调度本身不受支持,导致访问者模式作为连接两个(或更多)单个调度的方式,以便具有多调度代理。 / p>
多次发送的想法 - 基本上 - 允许像
这样的调用 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*);
}
请注意,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); }
...
};
现在,像pa->fn(pb)
这样的调用,如果pa指向derived_a1,pb指向derived_b1,最终会转到derived_a1::on_visit(derived_b1*)
。
答案 1 :(得分:13)
访客模式是一个解决方案,它实现了双重调度的行为。还可以有其他几种解决方案。术语 double dispatch 本身并不提供解决方案的任何想法,实际上这是一个问题,其解决方案由访客模式提供。
在C#(4.0)中,可以使用dynamic
关键字来实现双重调度,在这种情况下,不需要访问者模式。以下是使用dynamic
关键字双重调度问题的解决方案:
答案 2 :(得分:5)
动态调度是指一般情况下基于运行时信息调度方法的概念。大多数OO系统(如在Java / C#/ C ++中)通常通过virtual
方法实现动态调度(无论所有方法是否都是虚拟的,都取决于语言);这限制了它们根据单个方法参数(隐式对象引用)进行分派。
通常,您可能希望根据任意数量的元素进行调度。例如,Double Dispatch是根据方法的两个参数分派的要求/能力。
另一方面,访客模式一般是Multi Dispatch的实现,因此特别是在这样的OO系统中是Double Dispatch。
答案 3 :(得分:3)
双重调度是一个技术问题,可以根据语言以不同的方式解决 - 某些语言可以直接支持双重调度。访客模式是一种可用于解决不同问题的模式。在C ++的情况下,它是用于双重调度的最常用(但不是唯一)解决方案,但它并不是专门用于此,并且即使在支持双重调度的语言中它也很有用。
答案 4 :(得分:1)