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.
I'm not very familiar with the Visitor pattern. Let's see if I got it right. Suppose you have a hierarchy of animals
(Suppose it is a complex hierarchy with a well-established interface.)
Now we want to add a new operation to the hierarchy, namely we want each animal to make its sound. As far as the hierarchy is this simple, you can do it with straight polymorphism:
But proceeding in this way, each time you want to add an operation you must modify the interface to every single class of the hierarchy. Now, suppose instead that you are satisfied with the original interface, and that you want to make the fewest possible modifications to it.
The Visitor pattern allows you to move each new operation in a suitable class, and you need to extend the hierarchy's interface only once. Let's do it. First, we define an abstract operation (the "Visitor" class in GoF) which has a method for every class in the hierarchy:
Then, we modify the hierarchy in order to accept new operations:
Finally, we implement the actual operation, without modifying neither Cat nor Dog:
Now you have a way to add operations without modifying the hierarchy anymore. Here is how it works:
Visitor Pattern as the same underground implementation to Aspect Object programming..
For example if you define a new operation without changing the classes of the elements on which it operates
In my opinion, the amount of work to add a new operation is more or less the same using
Visitor Pattern
or direct modification of each element structure. Also, if I were to add new element class, sayCow
, the Operation interface will be affected and this propagates to all existing class of elements, therefore requiring recompilation of all element classes. So what is the point?Visitor
Visitor structure:
Use Visitor pattern if:
Even though Visitor pattern provides flexibility to add new operation without changing the existing code in Object, this flexibility has come with a drawback.
If a new Visitable object has been added, it requires code changes in Visitor & ConcreteVisitor classes. There is a workaround to address this issue : Use reflection, which will have impact on performance.
Code snippet:
Explanation:
Visitable
(Element
) is an interface and this interface method has to be added to a set of classes.Visitor
is an interface, which contains methods to perform an operation onVisitable
elements.GameVisitor
is a class, which implementsVisitor
interface (ConcreteVisitor
).Visitable
element acceptVisitor
and invoke a relevant method ofVisitor
interface.Game
asElement
and concrete games likeChess,Checkers and Ludo
asConcreteElements
.In above example,
Chess, Checkers and Ludo
are three different games ( andVisitable
classes). On one fine day, I have encountered with a scenario to log statistics of each game. So without modifying individual class to implement statistics functionality, you can centralise that responsibility inGameVisitor
class, which does the trick for you without modifying the structure of each game.output:
Refer to
oodesign article
sourcemaking article
for more details
Decorator
Related posts:
Decorator Pattern for IO
When to Use the Decorator Pattern?
your question is when to know:
i do not first code with visitor pattern. i code standard and wait for the need to occur & then refactor. so lets say you have multiple payment systems that you installed one at a time. At checkout time you could have many if conditions (or instanceOf) , for example :
now imagine i had 10 payment methods, it gets kind of ugly. So when you see that kind of pattern occuring visitor comes in handly to seperate all that out and you end up calling something like this afterwards:
You can see how to implement it from the number of examples here, im just showing you a usecase.
Based on the excellent answer of @Federico A. Ramponi.
Just imagine you have this hierarchy:
What happen if you need to add a "Walk" method here? That will be painful to the whole design.
At the same time, adding the "Walk" method generate new questions. What about "Eat" or "Sleep"? Must we really add a new method to the Animal hierarchy for every new action or operation that we want to add? That's ugly and most important, we will never be able to close the Animal interface. So, with the visitor pattern, we can add new method to the hierarchy without modifying the hierarchy!
So, just check and run this C# example: