在python中实现Visitor设计模式时是否需要accept()?

时间:2015-12-01 08:36:10

标签: python design-patterns visitor-pattern

我发现很多人在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()

在python中实现访问者设计模式

1 个答案:

答案 0 :(得分:0)

好吧,我不认为我的答案会完全解决你的问题,但无论如何:

  1. 当你从节点中删除accept方法时,你会检查它是不是访问者模式实现(因为它清楚地看到at the diagram);

  2. 编写代码的方式仅适用于支持内省的语言,允许动态获取实例的类(type introspection)。我们有在Python中使用的工具,但在其他语言中,这些工具可能不易于实现/阅读。

  3. 还有另一个专门针对stackoverflow问题的线程:" What is the point of accept() method in Visitor pattern?"。你可以在这里找到很多有趣的细节,例如当节点是复杂的复合结构并因此将accept方法调用委托给它的部分时。