mardi 1 décembre 2015

Is accept() necessary when implementing Visitor design pattern in python?

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 by accept()?

Aucun commentaire:

Enregistrer un commentaire