views:

2195

answers:

8

I keep seeing references to the visitor pattern in blogs but I've got to admit, I just don't get it. I read the wikipedia article for the pattern and I understand its mechanics but I'm still confused as to when I'd use it.

As someone who just recently really got the decorator pattern and is now seeing uses for it absolutely everywhere I'd like to be able to really understand intuitively this seemingly handy pattern as well.

+18  A: 

The reason for your confusion is probably that the Visitor is a fatal misnomer. Many (prominent1!) programmers have stumbled over this problem. What it actually does is implement double dispatching in languages that don't support it natively (most of them don't).


1) My favourite example is Scott Meyers, acclaimed author of “Effective C++”, who called this one of his most important C++ aha! moments ever.

Konrad Rudolph
+5  A: 

One way to look at it is that the visitor pattern is a way of letting your clients add additional methods to all of your classes in a particular class hierarchy.

It is useful when you have a fairly stable class hierarchy, but you have changing requirements of what needs to be done with that hierarchy.

The classic example is for compilers and the like. An Abstract Syntax Tree (AST) can accurately define the structure of the programming language, but the operations you might want to do on the AST will change as your project advances: code-generators, pretty-printers, debuggers, complexity metrics analysis.

Without the Visitor Pattern, every time a developer wanted to add a new feature, they would need to add that method to every feature in the base class. This is particularly hard when the base classes appear in a separate library, or are produced by a separate team.

(I have heard it argued that the Visitor pattern is in conflict with good OO practices, because it moves the operations of the data away from the data. The Visitor pattern is useful in precisely the situation that the normal OO practices fail.)

Oddthinking
A: 

At my work we recently used it for visiting every node in a tree structure.

John Topley
+20  A: 
Federico Ramponi
A class hierarchy is confusing as a first example. A simpler hierarchy of uniform nodes (like XML nodes or directories) is often easier to explain.
S.Lott
For myself, I prefer an example like that with a short sample of code like that.
Luc M
S.Lott, walking a tree is not actually the visitor pattern. (It's the "hierarchical visitor pattern", which is confusingly completely different.) There's no way to show the GoF Visitor pattern without using inheritance or interface implementation.
munificent
+1 Made sense to me. Can't go wrong with the old animal/dog/cat example!
Repo Man
+13  A: 

Q: When would I use the Visitor pattern?

A: You don't! You just say who you are and get someone else to use it for you!

:-)

Bill Karwin
Well, no... The boss sends a VisitorImplementer to you, then you tell him who you are and let him use your computer. :D
Federico Ramponi
Presuming your computer is public, of course.
Federico Ramponi
haha. You do not understand the Visitor pattern if you don't find this funny.
jop
I guess this will be my litmus test
George Mauer
+2  A: 

The Visitor design pattern works really well for "recursive" structures like directory trees, XML structures, or document outlines.

A Visitor object visits each node in the recursive structure: each directory, each XML tag, whatever. The Visitor object doesn't loop through the structure. Instead Visitor methods are applied to each node of the structure.

Here's a typical recursive node structure. Could be a directory or an XML tag. [If your a Java person, imagine of a lot of extra methods to build and maintain the children list.]

class TreeNode( object ):
    def __init__( self, name, *children ):
        self.name= name
        self.children= children
    def visit( self, someVisitor ):
        someVisitor.arrivedAt( self )
        someVisitor.down()
        for c in self.children:
            c.visit( someVisitor )
        someVisitor.up()

The visit method applies a Visitor object to each node in the structure. In this case, it's a top-down visitor. You can change the structure of the visit method to do bottom-up or some other ordering.

Here's a superclass for visitors. It's used by the visit method. It "arrives at" each node in the structure. Since the visit method calls up and down, the visitor can keep track of the depth.

class Visitor( object ):
    def __init__( self ):
        self.depth= 0
    def down( self ):
        self.depth += 1
    def up( self ):
        self.depth -= 1
    def arrivedAt( self, aTreeNode ):
        print self.depth, aTreeNode.name

A subclass could do things like count nodes at each level and accumulate a list of nodes, generating a nice path hierarchical section numbers.

Here's an application. It builds a tree structure, someTree. It creates a Visitor, dumpNodes.

Then it applies the dumpNodes to the tree. The dumpNode object will "visit" each node in the tree.

someTree= TreeNode( "Top", TreeNode("c1"), TreeNode("c2"), TreeNode("c3") )
dumpNodes= Visitor()
someTree.visit( dumpNodes )

The TreeNode visit algorithm will assure that every TreeNode is used as an argument to the Visitor's arrivedAt method.

S.Lott
+6  A: 

Finally got it after reading this article by Jermey Miller on my blackberry while stuck waiting in a lobby for two hours. It's long but gives a wonderful explanation of double-dispatch, visitor, and composite, and what you can do with these.

George Mauer
The article is not linked.
Daniel
I personally didn't understand the visitor pattern until I read this article: http://andymaleh.blogspot.com/2008/04/scalas-pattern-matching-visitor-pattern.html. Visitors are used for navigating hierarchies of data, they're a poor mans version of pattern matching on union types.
Juliet
+4  A: 

Everyone here is correct, but I think it fails to address the "when". First, from Design Patterns:

Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Now, let's think of a simple class hierarchy. I have classes 1, 2, 3 and 4 and methods A, B, C and D. Lay them out like in a spreadsheet: the classes are lines and the methods are columns.

Now, Object Oriented design presumes you are more likely to grow new classes than new methods, so adding more lines, so to speak, is easier. You just add a new class, specify what's different in that class, and inherits the rest.

Sometimes, though, the classes are relatively static, but you need to add more methods frequently -- adding columns. The standard way in an OO design would be to add such methods to all classes, which can be costly. The Visitor pattern makes this easy.

By the way, this is the problem that Scala's pattern matches intends to solve.

Daniel