访问者行为模式的优点和缺点是什么?

What are advanteges and disadvantages of the Visitor behavior pattern?

我正在做一个关于访问者设计模式的演示,我了解它是如何工作的,但我还没有找到 "defined" 优点和缺点,我不想推测优点或对自己不利,因为我可以设置虚假信息。

以下是我对 Visitor 模式的一些看法:

优点:

  • 主要优势:向所有元素添加操作非常简单,因为您只需实现访问者界面。无需修改每个 Element 对象即可添加操作。
  • 您将许多元素共有的操作重新组合到一个访问者中 class。只有该操作的代码在该访问者 class 中。如果您想具体了解某个操作的代码,可以使代码更易于阅读。

缺点:

  • 您的访问者可以修改您的元素,因为元素的实例已发送给访问者。不推荐这样做,因为它会导致 side effects。这可以通过使您的对象不可变来解决。
  • Element对象的代码分布在所有Visitor对象中。因此,Element 的逻辑存在于许多 classes 中。如果您想查看一个 Element 对象的代码,它会使代码更难阅读。
  • 每次操作都需要一个新访客class。

除了@GammaOmega 所写的,访问者模式的另一个缺点是它是 侵入性的 因为,为了支持访问者模式,类 在树结构必须提供一个 accept() 操作。如果您需要使用不提供 accept() 操作的 third-party 树结构,则不能使用访问者模式。

下面的伪代码显示了如何通过 accept() 操作进行 visitor-like 树遍历而不污染树节点 类。

void walk(TreeNode * node, NodeProcessor * processorObj)
{
  //--------
  // This switch statement is used instead of accept() operations
  // on nodes in a tree.
  //--------
  switch (node->getNodeType()) {
  case NT_module:
    processorObj->processModule((TreeModuleNode*)node);
    break;
  case NT_interface:
    processorObj->processInterface((TreeInterfaceNode*)node);
    break;
  ... // other cases omitted for brevity
  }

  //--------
  // Recurse down the tree
  //--------
  if (node->isScope()) {
    TreeScopeNode * scope = (TreeScopeNode*)(node);
    foreach child in scope->getChildren() {
      walk(child, processorObj);
    }
  }
}