c++/java/c#等面向对象的编程语言,都是单次分发,有些场景下单次分发已经不能满足要求,因此可以借助访问者设计模式完成二次分发设计:
// VisitAccept.h
#pragma once
class Acceptor;
class Visitor
{
public:
virtual void visit(Acceptor* acp);
};
class Visitor1 :public Visitor
{
public:
virtual void visit(Acceptor* acp);
};
class Visitor2 :public Visitor
{
public:
virtual void visit(Acceptor* acp);
};
class Visitor3 :public Visitor
{
public:
};
class Acceptor
{
public:
virtual void accept(Visitor* v);
virtual void accept(Visitor1* v);
virtual void accept(Visitor2* v);
};
#include <exception>
#include "VisitAccept.h"
void Visitor::visit(Acceptor* acp)
{
throw std::runtime_error("Not Implementation");
}
void Visitor1::visit(Acceptor* acp)
{
acp->accept(this);//第二次分发,利用Acceptor的成员函数重载,进入到Acceptor不同的处理流程。
}
void Visitor2::visit(Acceptor* acp)
{
acp->accept(this);
}
void Acceptor::accept(Visitor* v)
{
printf("accept visitor commonly.\n");
v->visit(this);//第一次分发,利用虚函数表,根据v的运行时类型,进入到相应的处理流程。
}
void Acceptor::accept(Visitor1* v)
{
printf("accept visitor1 certainly.\n");
}
void Acceptor::accept(Visitor2* v)
{
printf("accept visitor2 certainly.\n");
}
在使用时,受访者可以根据不同的访问者类型,执行不同的处理逻辑。新增访问者类型时(如Visitor3),先继承Visitor基类,重写visit函数,并且在Acceptor中增加重载方法处理Visitor3类型的访问者即可。
#include "VisitAccept.h"
int main()
{
Visitor* v1 = new Visitor1;
Visitor* v2 = new Visitor2;
Acceptor acp;
acp.accept(v1);
acp.accept(v2);
getchar();
Visitor* v3 = new Visitor3;
acp.accept(v3);
return 0;
}