分派过程就是确定一个方法调用的过程,双分派就是根据运行时多个对象的类型确定方法调用的过程。
想象这样一个客户服务的场景,一般客户支持有一级支持和二级支持。一级支持一般解决比较简单的问题,如果问题解决不了,就会由二级支持来解决。
定义一般问题:
class Problem
{
public:
Problem(){}
virtual ~Problem(){}
};
定义特殊问题:
class SpecialProblem:public Problem
{
public:
SpecialProblem(){}
~SpecialProblem(){}
};
定义一级支持:
class Supporter
{
public:
Supporter(){}
virtual ~Supporter(){}
virtual void solve(Problem &p)
{
std::cout<<"一级支持解决一般问题"<<std::endl;
}
virtual void solve(SpecialProblem &sp)
{
std::cout<<"一级支持解决特殊问题"<<std::endl;
}
};
定义资深支持:
class SeniorSupporter:public Supporter
{
public:
SeniorSupporter(){}
~SeniorSupporter(){}
void solve(Problem &p)
{
std::cout<<"资深支持解决一般问题"<<std::endl;
}
void solve(SpecialProblem &sp)
{
std::cout<<"资深支持解决特殊问题"<<std::endl;
}
};
下面是测试类:
int main()
{
Problem *p=new Problem();
Problem *sp=new SpecialProblem();
Supporter *s=new SeniorSupporter();
s->solve(*p);
s->solve(*sp);
system("Pause");
return 1;
}
以下是预料中的错误运行结果:
s->solve(*p);
s->solve(*sp);
class Problem
{
public:
Problem(){}
virtual ~Problem(){}
virtual void solve(Supporter *s)
{
s->solve(*this);
}
//*virtual void solve(SeniorSupporter *sp)
//{
// sp->solve(*this);
//}
};
在SpecialProblem,增加如下方法,在方法调用时,将自身传入:
class SpecialProblem:public Problem
{
public:
SpecialProblem(){}
~SpecialProblem(){}
void solve(Supporter *s)
{
s->solve(*this);
}
//void solve(SeniorSupporter *s)
//{
// s->solve(*this);
//}
};
看看现在的测试代码:
int main()
{
Problem *p=new Problem();
Problem *sp=new SpecialProblem();
Supporter *s=new SeniorSupporter();
p->solve(s);
sp->solve(s);
system("Pause");
return 1;
}
以下是运行结果:
现在,通过调用:
p->solve(s);
sp->solve(s);
来实现两次动态分派,第一次是problem中solve方法的多态,第二次是supporter中solve方法的多态。
Visitor模式也使用了类似的方式:
Visitor模式中的Accept也是一个double dispatch操作,它的含义决定于两个类型:Visitor的类型和Element的类型。这是Visitor模式的关键所在:得到执行的操作不仅决定于Visitor的类型还决定于它访问的Element的类型。而采取的解决方案如上图,没有将操作静态的绑定在Element接口中,而是将其安放在一个Visitor中,并使用Accept在运行时进行绑定。