我写了访客模式如下,但我不明白什么是单一和双重调度。 AFAIK,单个调度是基于调用者类型调用一个方法,其中double dispatch根据调用者类型和参数类型调用方法。
我认为双重调度是在单个类层次结构中发生的,但为什么访问者类有两个类层次结构但它仍被视为双重调度。
void floppyDisk::accept(equipmentVisitor* visitor)
{
visitor->visitFloppyDisk(this);
}
void processor::accept(equipmentVisitor* visitor)
{
visitor->visitProcessor(this);
}
void computer::accept(equipmentVisitor* visitor)
{
BOOST_FOREACH(equipment* anEquip, cont)
{
anEquip->accept(visitor);
}
visitor->visitComputer(this);
}
void visitFloppyDisk(floppyDisk* );
void visitProcessor(processor* );
void visitComputer(computer* );
请使用我提供的示例代码解释。
AFAIK,第一次调度发生在调用accept的对象上,第二次调度发生在调用visit方法的对象上。
感谢。
答案 0 :(得分:9)
简而言之,单一调度是指一个方法对一个参数的类型(包括隐式this
)具有多态性。双重调度是两个参数的多态性。
第一个的典型示例是标准虚方法,它对包含对象的类型是多态的。第二个可以通过访客模式实现。
[更新] 我假设在您的示例中,floppyDisk
,processor
和computer
都是从定义{{1}的公共基类继承的}作为虚拟方法。同样,accept
方法应该在visit*
中声明为虚拟,其中应该有一些具有不同equipmentVisitor
实现的派生类。的 [/更新] 强>
假设上述情况,visit*
和accept
上的this
都是多态的。 floppydisk,处理器和计算机都有自己的equipmentVisitor
实现,因此当访问者调用accept
时,将根据被调用者的类型调度cal。然后被叫方回拨访问者类型特定的访问方法,并根据访问者的实际类型调度此调用。
理论上也可以有三重,四重等调度,虽然我从未见过这在实践中实现过(在语言中不支持双重和更高级别的调度,也就是说 - 我似乎记得Smalltalk确实?)。使用C ++和类似语言的Visitor进行双重调度本身已经非常令人难以置信,因此三次和更高级别调度的实现过于复杂,无法在实际应用中使用。
答案 1 :(得分:6)
在您的示例中,您缺少该机制的基础知识:继承和虚拟。除了代码之外,让我们假设以下类层次结构:
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);
由于采用了双重调度机制,最后一行允许任何equipmentVisited
接受任何equipmentVisitor
,无论它们的实际静态类型是什么。最终,将为正确的类调用正确的函数。
总结:
accept()