We have used the visitor pattern to conveniently access and manipulate a parse tree (together with JavaCompilerCompiler
). It is a very powerful pattern that is easy to mess up. Logical mistakes may be hard to trace. --FredrikRubensson
See also UsesOfGofPatterns
Visitor gives java a way of implementing something similar to the friend concept. This has come in useful for us a few times when we had sensitive information we wanted to make private to a class, but needed access to the info occasionally outside the class (but wanted to controll what object got access). It basically worked like this:
We had a password privately stored in a class. We needed to get access to that method outside the object, so we made a getPassword method that returned a void and accepted an interface with setPassword on it. At this point we were able to check information about the object passed in and see if it was qualified for the password information. If it was we called setPassword, and it went happily on its way. If not we did not set the password, but threw an exception. The essential point here, is that we were able to make the data accessible to objects that we specifically decided were qualified for the password info without making the info public. --LanceLarsen?
There is an interesting extension of the VisitorPattern
, called the SwitchSwitchablePattern
, discussed at [http://www.sable.mcgill.ca/publications/thesis/#gagnonMastersThesis
] and used in the SableCC parser generator. It addresses the issue that VisitorPattern
makes it hard to add new classes to the hierarchy of objects that can be 'visited'. -- LaurentBossavit
for a different take on the traditional VisitorPattern
Wouldn't it be great if the DocumentObjectModel
used the visitor pattern? It needs extreme use of type-code/cast switching.
See http://www.quiotix.com/downloads/html-parser/ for a visitor to a proprietary DOM for HTML.
I've never been able to escape the feeling that this pattern should also be called "Short Circuit Good Design". You have an object with rules for protecting its internal representation. Visitor says (to me) "violate the original design abstraction for the purposes of rummaging around in the guts without adapting the design or considering the consequences". Perhaps it should be called "Use the Wrong Tool for the Job because We're Too Lazy to Create the Right One".
No, that's using visitor badly; see Robert di Falco's argument in HierarchicalVisitorPattern
about the inevitablity of breaking its idiom. You have an object with rules for protecting its internal representation, but you cannot know in advance all the operations you might want to perform over that object. So, provide a facility to perform new operations without cluttering the object's contract. Separate action from data. BillDehora
OK, so what is the right abstraction? Can you give an example of where
it seems natural to use Visitor, but in fact the right solution is a
completely different approach?
Note that there are other design patterns, such as Mediator and Strategy,
that can also be considered to "violate the original design abstraction".
No pattern should ever be used without considering the consequences.
So, I'd like to see a "counterexample" so I can tell whether it is unique
to Visitor, or just another example of pattern misuse. -RalphJohnson
In my experience, Visitor is useful to model non-orthogonal operations on a stable class hierarchy. Most of the unease with this pattern seems to stem from the assumption that ALL operations related to a class need to be present in the class itself. Not necessarily.
In my case, we had an object model that had been stable for some time. All the classes in the hierarchy defined basic, orthogonal operations (ones that needed to directly use the state information inside and could not be written using the other public operations). The operation that I needed to add was more peripheral, like extracting the XML representation of the entire hierarchy of the objects.
This was done using the Visitor pattern. The existing code didn't need to be mucked around with in a big way. Plus, all XML related logic was in one place. So, if I wanted to switch the XML parser, for example, I had to change only one place and again, not much around with the class hierarchy in any way.
Any thoughts? --SriramGopalan
A Visitor is a double dispatch, as noted in the book, historically known as a callback hook.
The GoF book suggests it as a way of dynamically adding methods that are then called from the class which contains the method? Why bother? Just call the method with the object as a parameter. I don't see why the pattern is appropriate as a static 'futureproofing' mechanism.
The historical usages of callbacks are:
- where the callback involves information which the called function doesn't have access to and vice versa.
- where the callback event needs to be controlled by the calling element.
- where the callback is being used as a functor style hook.
Arguably these issues are the same, I tend to divide them [logically], albeit the [physical] solution is identical.
In order, the first point improves encapsulation. The basic Visitor pattern passes the entire object as a parameter when this may not be appropriate, thus the arguments about encapsulation breakage. Instead one should only pass the information between the elements that is necessary. As such this usage is a form of dynamic linkage.
The second point allows non-trusted objects to be tested, and the call aborted if the tests fail. Thus the usage as a security or type-testing mechanism. In any case, the point is one of intercepting the calling event.
Finally, the functor hook is an obvious division of concerns as seen in internal iterators.
This list is probably not complete. YMMV :). --RichardHenderson.