User Tools

Site Tools


python:visitorpat

Visitor Pattern

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

python/visitorpat.txt · Last modified: 2013/03/16 17:41 (external edit)