11.01.2012
#!/usr/bin/env python # -*- coding: utf-8 -*- # # VISITOR PATTERN # # The Visitable class (e.g. Visitable_List) decides how it calls the Visitor class (which method) class Visitable_List(list): def accept(self, visitor): visitor.count_list_elem(self) class Visitable_String(str): def accept(self, visitor): visitor.print_string(self) # holds the algorithm applied to data class Visitor(object): def count_list_elem(self, obj): print "Elem #:{}".format(len(obj)) def print_string(self, obj): print obj
Usage:
a_list = Visitable_List([1, 3, 4]) a_list.accept(Visitor()) a_string = Visitable_String("Some visitable string") a_string.accept(Visitor())
The need for accept() method should be further simplified (but the methods should rely on some naming convention within Visitor class). Let's take a look:
#!/usr/bin/env python # -*- coding: utf-8 -*- # # VISITOR PATTERN (IMPROVED) # # it removes the need for accept() method but the methods in Visitor # should follow a specified naming convention # The Visitable class (e.g. Visitable_List) are linked with the visit_* methods class Visitable_List(list): pass class Visitable_String(str): pass # holds the algorithm applied to data class Visitor(object): def visit_list(self, obj): print "Elem #:{}".format(len(obj)) def visit_str(self, obj): print obj def pay_visit(visited, visitor): cls_name = visited.__class__.__base__.__name__ method_name = 'visit_{}'.format(cls_name) # the same as the methods within Visitor class method = getattr(visitor, method_name, None) if method: method(visited)
A simple example of usage:
pay_visit(Visitable_List([1,2,3]), Visitor()) pay_visit(Visitable_String("Some visitable string"), Visitor())