The PEAK Developers' Center   Diff for "VisitorRevisited" UserPreferences
 
HelpContents Search Diffs Info Edit Subscribe XML Print View
Ignore changes in the amount of whitespace

Differences between version dated 2004-11-16 00:13:33 and 2005-01-08 03:13:09 (spanning 4 versions)

Deletions are marked like this.
Additions are marked like this.

The "Classic" Visitor Pattern
-----------------------------
 
The "Classic" Visitor pattern, from the `Gang of Four Book`__, tries to solve this problem by putting the algorithm into a "Visitor" class, and using a ``visit()`` method in the target classes, that selects the correct behavior from the Visitor class. For example, if we were writing a "pretty printer" Visitor, we might make a ``PrettyPrinter`` class with methods like ``visit_list()``, ``visit_string()``, and so on, that have the code for printing that kind of object. Then, we would add a simple ``accept()`` method like this::
The "Classic" Visitor pattern, from the `Gang of Four Book`__, tries to solve this problem by putting the algorithm into a "Visitor" class, and using an ``accept()`` method in the target classes, that selects the correct behavior from the Visitor class. For example, if we were writing a "pretty printer" Visitor, we might make a ``PrettyPrinter`` class with methods like ``visit_list()``, ``visit_string()``, and so on, that have the code for printing that kind of object. Then, we would add a simple ``accept()`` method like this::
 
     def accept(self, visitor):
         return visitor.visit_list(self)

 
to each of our target classes. As you can see, the method above calls the visitor's ``visit_list()`` method, so that the visitor knows what kind of object it's working on. Then, when we need a new operation, like exporting to XML, we just write an ``XMLExporter`` class with a different ``visit_list()`` method.
 
Of course, there are two problems with this approach, at least in Python. First, we can't modify built-in types like ``list``, so if we take this approach, we won't be able to pretty-print lists or export them to XML. We could only use this approach with new classes that we create, or classes that somebody already put a ``accept()`` method in. Second, it seems really silly to write a bunch of methods just to tell the visitor what type something is. Isn't there an easier way to do this?
Of course, there are two problems with this approach, at least in Python. First, we can't modify built-in types like ``list``, so if we take this approach, we won't be able to pretty-print lists or export them to XML. We could only use this approach with new classes that we create, or classes that somebody already put an ``accept()`` method in. Second, it seems really silly to write a bunch of methods just to tell the visitor what type something is. Isn't there an easier way to do this?
 
 
Extrinsic Visitor

 
So, it's definitely easy to code. (But if you need raw performance, you *will* want to use a cache: the extra attribute access and string concatenation are 2-3 times slower than looking up the class in a dictionary, and if you have very large data structures the difference will add up very quickly.)
 
There is a drawbacks to this approach, however. As commonly coded in Python, the Extrinsic Visitor pattern does not have any way to deal with inheritance.
There is one drawback to this approach, however. As commonly coded in Python, the Extrinsic Visitor pattern does not have any way to deal with inheritance.
 
For example, let's say your ``PrettyPrinter`` class has a ``visit_list()`` method. And somebody subclasses ``list`` to make ``MyList``. You're going to have to add a ``visit_MyList()`` to your ``PrettyPrinter`` class, even though in all probability the ``visit_list()`` method would work just fine.
 

    def print_list(target,stream):
        # pretty-print a list (or subclass thereof)
        stream.write("[")
        for item in list:
        for item in target:
             pretty_print(item,stream)
             stream.write(",")
        stream.write("]")

PythonPowered
ShowText of this page
EditText of this page
FindPage by browsing, title search , text search or an index
Or try one of these actions: AttachFile, DeletePage, LikePages, LocalSiteMap, SpellCheck