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.
When you want to have function objects on union data types, you will need visitor pattern.
You might wonder what function objects and union data types are, then it's worth reading http://www.ccs.neu.edu/home/matthias/htdc.html
I really like the description and the example from http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Visitor.html.
I didn't understand this pattern until I came across with uncle bob article and read comments. Consider the following code:
While it may look good since it confirms to Single Responsibility it violates Open/Closed principle. Each time you have new Employee type you will have to add if with type check. And if you won't you'll never know that at compile time.
With visitor pattern you can make your code cleaner since it does not violate open/closed principle and does not violate Single responsibility. And if you forget to implement visit it won't compile:
The magic is that while
v.Visit(this)
looks the same it's in fact different since it call different overloads of visitor.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.]
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 thevisit
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 thevisit
method callsup
anddown
, the visitor can keep track of the depth.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 aVisitor
,dumpNodes
.Then it applies the
dumpNodes
to the tree. ThedumpNode
object will "visit" each node in the tree.The TreeNode
visit
algorithm will assure that every TreeNode is used as an argument to the Visitor'sarrivedAt
method.There are at least three very good reasons for using the Visitor Pattern:
Reduce proliferation of code which is only slightly different when data structures change.
Apply the same computation to several data structures, without changing the code which implements the computation.
Add information to legacy libraries without changing the legacy code.
Please have a look at an article I've written about this.
Thanks for the awesome explanation of @Federico A. Ramponi, I just made this in java version. Hope it might be helpful.
Also just as @Konrad Rudolph pointed out, it's actually a double dispatch using two concrete instances together to determine the run-time methods.
So actually there is no need to create a common interface for the operation executor as long as we have the operation interface properly defined.
As you expect, a common interface will bring us more clarity though it's actually not the essential part in this pattern.