3

I found many people implement Visitor design pattern in python as follows:

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)

For Java or other C-like static language, they use accept() to implement multi-dispatch. Because the visit() method choose specific override method only by the static type of reference. For example:

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); 

The visitor will invoke the method for Node rather than AddNode. Thus, accept() is necessary to get the "real" type of instance as follow:

public class AddNode extends Node implements IVisitable{
    void accept(IVisitor visitor) {
        visitor.visit(this)
    }
}

However, the type could be directly extract from instance in python. The Visitor could be implement as follow:

class Visitor(object):
    def visit(self, node):
        classname = node.__class__.__name__
        _visit = getattr(self, '_visit_'+classname)
        _visit(node)
    def _visit_AddNode(self, node):
        pass

Then, we could visit the node by using visit() directly

node = AddNode()
visitor = Visitor()
visitor.visit(node)

This way is more natural and simpler. Why do people still implement Visitor design pattern in python with accept()?

Yyao
  • 395
  • 3
  • 17

1 Answers1

1

Well, I don't think that my answer will resolve your question completely, but anyway:

  1. when you remove accept method from the nodes you check it stops being Visitor pattern implementation (as it's clearly seen at the diagram);

  2. the way you wrote the code works only for the languages supporting introspection in a way, which allows to dynamically get the class of an instance (type introspection). We have tools to do that in Python, but in other languages that can be not so easy to implement / pleasant to read.

There's another thread devoted to the problem on stackoverflow: "What is the point of accept() method in Visitor pattern?". You can find here a lot of interesting details, e.g. case when node is a sophisticated compound structure and thus delegates accept method call to its parts.

Community
  • 1
  • 1
everyonesdesign
  • 356
  • 2
  • 9