使用访客设计模式的一个很好的理由?

die*_*rre 5 design-patterns visitor-pattern

在你告诉我已经存在类似的问题之前,是的,我知道,我已经读过.但那里的问题集中在何时,我对其原因感兴趣.

我知道事情是如何运作的.经典的动物,狗,猫的例子总是像魅力一样.

事情是这个代码

int main()
{
    Cat c;
    Sound theSound;
    c.letsDo(&theSound);
}
Run Code Online (Sandbox Code Playgroud)

对我来说似乎很不自然.为什么?

我的意思是,是啊,这样我有我的狗和猫的模型未分化(我第一次用英语BTW这个词),因为真正的implentation是声音类下隐藏,但不只是为了压低你的代码的方式?多态性不足以做这样的事吗?

对我而言,不同之处在于,使用多态性,您必须编辑每个类(但模型保持不变,对吧?)而您只需使用访问者设计模式编辑一个类.

Dir*_*irk 8

访问者模式允许您执行某些操作,而这些操作依赖于多态性不会:使用意外的用例.如果您正在编写库,这是一个重点.让我详细说明:

考虑使用访问者模式的经典示例,即对某些抽象语法树的节点上的操作.例如,要添加一些细节,您刚刚为SQL编写了一个解析器库,它接受字符串,解析它们,并返回它在输入中找到的东西的AST.除非您能够预测客户端代码可能具有此类AST的所有潜在用例,否则您必须提供一种"通用"方式来处理AST.提供类似DOM的访问函数(getNodeType,getParentNode,getPreviousNode)是一种方法.这里的问题是,这会给您图书馆的客户带来沉重的负担,因为他们需要自己进行调度.更重要的是,他们需要非常详细地了解每个可能的节点类型遵循哪些指针:

void 
walk_tree(AstNode* node) 
{
    switch( node->getNodeType() ) {
    case SELECT_NODE:
        for( AstNode* child = node->getFirstChild(); child; child = child->getNextNode() ) {
             walk_tree(child);
        }
        break;
    ...
    }
}
Run Code Online (Sandbox Code Playgroud)

访问者模式将此负担从客户端移动到库中.