User Tools

Site Tools


python:visitorpat

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

python:visitorpat [2013/03/16 17:41] (current)
Line 1: Line 1:
 +==== Visitor Pattern ====
 +11.01.2012
  
 +
 +<code python>
 +#​!/​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
 +</​code>​
 +
 +Usage:
 +
 +<code python>
 +a_list = Visitable_List([1,​ 3, 4])
 +a_list.accept(Visitor())
 +
 +a_string = Visitable_String("​Some visitable string"​)
 +a_string.accept(Visitor())
 +</​code>​
 +
 +
 +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:
 +
 +<code python>
 +#​!/​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) ​       ​
 +</​code>​
 +
 +A simple example of usage:
 +
 +<code python>
 +pay_visit(Visitable_List([1,​2,​3]),​ Visitor())
 +pay_visit(Visitable_String("​Some visitable string"​),​ Visitor())
 +</​code>​
python/visitorpat.txt ยท Last modified: 2013/03/16 17:41 (external edit)