我发现很多人在python中实现了访问者设计模式,如下所示:
class Node(object):
def accept(self, visitor):
visitor.visit(self)
# some code ...
class Visitor(object):
def visit(self, node):
# invoke corresponding method according to the type of node
# ...
node = Node()
visitor = Vistor()
node.accept(visitor)
对于Java或其他类似C的静态语言,他们使用accept()
来实现多分派。因为visit()
方法仅通过静态类型的引用选择特定的覆盖方法。例如:
public class MyVisitor implements IVisitor {
void visit(AddNode node);
void visit(Node node);
}
Node node = AddNode(); // AddNode is derived from Node
new MyVisitor().visit(root);
访问者将调用Node
而不是AddNode
的方法。因此,accept()
是获得真实"实例类型如下:
public class AddNode extends Node implements IVisitable{
void accept(IVisitor visitor) {
visitor.visit(this)
}
}
但是,类型可以直接从python中的实例中提取。 Visitor
可以按照以下方式实施:
class Visitor(object):
def visit(self, node):
classname = node.__class__.__name__
_visit = getattr(self, '_visit_'+classname)
_visit(node)
def _visit_AddNode(self, node):
pass
然后,我们可以直接使用visit()
访问该节点
node = AddNode()
visitor = Visitor()
visitor.visit(node)
这种方式更自然,更简单。为什么人们仍然使用accept()
?
答案 0 :(得分:0)
好吧,我不认为我的答案会完全解决你的问题,但无论如何:
当你从节点中删除accept
方法时,你会检查它是不是访问者模式实现(因为它清楚地看到at the diagram);
编写代码的方式仅适用于支持内省的语言,允许动态获取实例的类(type introspection)。我们有在Python中使用的工具,但在其他语言中,这些工具可能不易于实现/阅读。
还有另一个专门针对stackoverflow问题的线程:" What is the point of accept() method in Visitor pattern?"。你可以在这里找到很多有趣的细节,例如当节点是复杂的复合结构并因此将accept
方法调用委托给它的部分时。