访问者行为模式的优点和缺点是什么?
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);
}
}
}
我正在做一个关于访问者设计模式的演示,我了解它是如何工作的,但我还没有找到 "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);
}
}
}