Computer Science Design Patterns/Visitor

{{Computer Science Design Patterns/Page The visitor pattern allows you to easily perform a given operation (function, algorithm, etc…) on each element of a complex structure. The benefit is that you can easily add other operations to perform and you can easily change the structure of the elements. The principle is that the classes that are used to perform the operations and the classes that scroll the structures are different. It also means that, if you know that you will always have only one operation to perform on the structure, this pattern is useless.
 * mode={{{mode|reading}}}
 * page={{{page|{{SUBPAGENAME}}}}}
 * stage=25
 * stage date=10 Aug, 2014
 * stage comment=Add more illustrations.
 * previous=Template method
 * next=
 * content=

Let's take the simple data class:

{{{!}} cellspacing="0px" style="border: solid 2px black; margin: auto;" {{!}} style="border-bottom: solid 1px black; text-align: center;"{{!}}Element {{!}}- {{!}} style="border-bottom: solid 1px black;"{{!}} {{!}}- {{!}} {{!}}}

We want to perform an operation on it. Instead of implementing it inside of the class, we will use a visitor class. A visitor class is a class that performs an action on an object. It will perform an action on a whole structure by being called for each element. However, for now, we only have one object. The visitor will be called by the visit method by the data object, and the object will be called by the accept method by the client:

{{{!}} cellspacing="0px" style="margin: auto;" {{!}} {{{!}} cellspacing="0px" style="border: solid 2px black; margin: auto; width: 100%;" {{!}} style="border-bottom: solid 1px black; text-align: center;"{{!}}Client {{!}}- {{!}} style="border-bottom: solid 1px black;"{{!}} {{!}}- {{!}} {{!}}} {{!}} {{!}} {{{!}} cellspacing="0px" style="border: solid 2px black; margin: auto; width: 100%;" {{!}} style="border-bottom: solid 1px black; text-align: center;"{{!}}< > Visitor {{!}}- {{!}} style="border-bottom: solid 1px black;"{{!}} {{!}}- {{!}} + visit(Element) {{!}}} {{!}}- {{!}} {{!}} {{!}} {{!}}- {{!}} {{{!}} cellspacing="0 px" style="border: solid 2px black; margin: auto; width: 100%;" {{!}} style="border-bottom: solid 1px black; text-align: center;"{{!}}< > Element {{!}}- {{!}} style="border-bottom: solid 1px black;"{{!}} {{!}}- {{!}} + accept(Visitor) {{!}}} {{!}} {{!}} {{{!}} cellspacing="0px" style="border: solid 2px black; margin: auto; width: 100%;" {{!}} style="border-bottom: solid 1px black; text-align: center;"{{!}}ConcreteVisitor {{!}}- {{!}} style="border-bottom: solid 1px black;"{{!}} {{!}}- {{!}} + visit(Element) {{!}}} {{!}}- {{!}} {{!}} {{!}} {{!}}- {{!}} {{{!}} cellspacing="0px" style="border: solid 2px black; margin: auto; width: 100%;" {{!}} style="border-bottom: solid 1px black; text-align: center;"{{!}}ConcreteElement {{!}}- {{!}} style="border-bottom: solid 1px black;"{{!}} {{!}}- {{!}} + accept(Visitor) {{!}}} {{!}} {{!}} {{!}}}

Then you can define a structure of data object and each object will call the accept method on its sub-elements. You may think that the main drawback of this pattern is that even if the visitor can process all the elements, it does not process it as a whole, i.e. it can't connect the different elements together, so the pattern is limited. Not at all. The visitor can keep information about the elements it has already visited (for example to log lines with appropriate indentation). If the visitor needs information from all the elements (for example to compute a percentage based on the sum), it can visit all the elements, store information, and actually process all the information after the last visit using another method. In other words, you can add states to your visitor.

This process is essentially equivalent to getting the collection's iterator, and using a while(iterator.hasNext) loop to invoke visitor.visit(iterator.next). The key difference is that the collection can decide exactly how to step through the elements. If you're familiar with iterators, you may be thinking that the iterator can decide how to step through, too, and the iterator is usually defined by the collection, so what's the difference? The difference is that the iterator is still bound to a while loop, visiting each element in succession, one at a time. With the visitor pattern, the collection could conceivably create a separate thread for each element and have the visitor visiting them concurrently. That's just one example of ways that the collection may decide to vary the method of visitation in a manner that can't be mimicked by an iterator. The point is, it's encapsulated, and the collection can implement the pattern in whatever way it feels is best. More importantly, it can change the implementation at any time, without affecting client code, because the implementation is encapsulated in the foreach method.

An example implementation of Visitor Pattern: String
To illustrate the visitor pattern, let's imagine we're reinventing Java's String class (it'll be a pretty ridiculous reinvention, but it'll be good for this exercise). We're not going to implement very much of the class, but let's assume that we're storing a set of chars that make up the string, and we have a method called getCharAt that takes an <tt>int</tt> as its only argument, and returns the character at that position in the string, as a <tt>char</tt>. We also have a method called <tt>length</tt> that takes no arguments, and returns an <tt>int</tt> that gives the number of characters in the string. Let's also assume that we want to provide an implementation of the visitor pattern for this class that will take an instance that implements the <tt>ICharacterVisitor</tt> interface (that we'll define, below), and calls its <tt>visit</tt> method for each character in the string. First we need to define what this <tt>ICharacterVisitor</tt> interface looks like:

Easy enough. Now, let's get down to our class, which we'll call <tt>MyString</tt>, and it looks something like this:

So, that was pretty painless. What can we do with this? Well, let's make a class called <tt>MyStringPrinter</tt>, which prints an instance of <tt>MyString</tt> to the standard output.

That was simple too. Of course, it could've been a lot simpler, right? We didn't need the <tt>foreach</tt> method in <tt>MyString</tt>, and we didn't need <tt>MyStringPrinter</tt> to implement the visitor, we could have just used the <tt>MyString</tt> classes <tt>getCharAt</tt> and <tt>length</tt> methods to set up our own <tt>for</tt> loop ourselves and printed each char inside the loop. Well, sure you could, but what if <tt>MyString</tt> isn't <tt>MyString</tt> but instead is <tt>MyBoxOfRocks</tt>.

Another example implementation of Visitor Pattern: Rock
In a box of rocks, is there a set order that the rocks are in? Unlikely. Of course <tt>MyBoxOfRocks</tt> has to store the rocks somehow. Maybe, it stores them in an array, and there is actually a set order of the rocks, even if it is artificially introduced for the sake of storage. On the other hand, maybe it doesn't. The point is once again that it is an implementation detail that you as the client of <tt>MyBoxOfRocks</tt> shouldn't have to worry about, and should never rely on.

Presumably, <tt>MyBoxOfRocks</tt> wants to provide someway for clients to get to the rocks inside it. It could, once again, introduce an artificial order to the rocks; assign each rock an index and provide a method like <tt>public Rock getRock(int aRockNumber)</tt>. Or maybe it wants to put names on all the rocks and let you access it like <tt>public Rock getRock(String aRockName)</tt>. But maybe it's really just a box of rocks, and there are no names, no numbers, no way of identifying which rock you want; all you know is you want the rocks. Alright, let's try it with the visitor pattern. First, our visitor interface (assume <tt>Rock</tt> is already defined somewhere, we don't care what it is or what it does):

Easy. Now out <tt>MyBoxOfRocks</tt>

Huh, what do you know, it does store them in an array. But what do we care now? We already wrote the visitor interface, and all we have to do now is implement it in some class that defines the actions to take for each rock, which we would have to do inside a <tt>for</tt> loop anyway. Besides, the array is private, our visitor doesn't have any access to that.

And what if the implementor of <tt>MyBoxOfRocks</tt> did a little homework and found out that comparing a number to zero is infinitesimally faster than comparing it to a non-zero value? Infinitesimal, sure, but maybe when you're iterating over 10 million rocks, it makes a difference (maybe!). So, he decides to change the implementation:

Now, he's iterating backwards through the array and saving a (very) little time. He's changed the implementation because he found a better way. You didn't have to worry about finding the best way, and you didn't have to change your code because the implementation is encapsulated. And that's not the half of it. Maybe, a new coder takes control of the project, and maybe this coder hates arrays and decides to totally change it:

Now, maybe in this instance, linked lists were a poor idea, not as fast as a nice lean array and a <tt>for</tt> loop. On the other hand, you don't know what else this class is supposed to do. Maybe, providing access to the rocks is only a small part of what it does, and linked lists fit in better with the rest of the requirements. In case I haven't said it enough yet, the point is that you as the client of <tt>MyBoxOfRocks</tt> don't have to worry about changes to the implementation, the visitor pattern protects you from it.

I have one more trick up my sleeve. Maybe, the implementor of <tt>MyBoxOfRocks</tt> notices that a lot of visitors are taking a really long time to visit each rock, and it's taking far too long for the <tt>foreach</tt> method to return because it has to wait for all visitors to finish. He decides it can't wait that long, and he also decides that some of these operations can probably be going on all at once. So, he decides to do something about it, namely, this:

If you're familiar with threads, you'll understand what's going on here. If you're not, I'll quickly summarize: a Thread is basically something that can run "simultaneously" with other threads on the same machine. They don't actually run simultaneously of course, unless maybe you have a multi-processor machine, but as far as Java is concerned, they do. So, for instance, when we created this new Thread called <tt>t</tt>, and defined what happens when the Thread is run (with the <tt>run</tt> method, naturally), we can then start the Thread, and it will start running, splitting cycles on the processor with other Threads, right away, doesn't have to wait for the current method to return. Likewise, we can start it running and then continue on our own way immediately, without waiting for it to return. So, with the above implementation, the only time we need to spend in this method is the time it takes to instantiate all the threads, <tt>start</tt> them running, and loop over the array; we don't have to wait for the visitor to actually visit each <tt>Rock</tt> before we can loop, we just loop right away, and the visitor does its thing on whatever CPU cycles it can swipe. The whole visiting process might take a long time – maybe even longer, if it looses some cycles because of the multiple threads, but the thread from which <tt>foreach</tt> was invoked doesn't have to wait for it to finish: it can return from the method and be on it's way much faster.

If you're confused about the use of the final <tt>Rock</tt> called "current" in the above code, it's just a bit of technicality using anonymous classes: they can't access non-final local variables. Even though <tt>fRocks</tt> doesn't fit into this category (it's not local, but an instance variable), <tt>i</tt> does. If you tried to remove this line and simply put <tt>fRocks[i]</tt> in the <tt>run</tt> method, it wouldn't compile.

So, what happens if you're the visitor, and you decide that you need to visit each rock one at a time? There's a number of reasons this might happen such as, if your <tt>visit</tt> method changes your instance variables, or it depends on the results of previous calls of <tt>visit</tt>. Well, the implementation inside the <tt>foreach</tt> method is encapsulated, so you don't know if it's using separate threads or not. Sure, you could figure it out with some fancy debugging, or some clever printing to std out, but wouldn't it be nice, if you didn't have to? And if you could be sure that, if they change it in the next version, your code will still work properly? Well, fortunately, Java provides the synchronize mechanism, which is basically an elaborate device for locking up blocks of code so that only one Thread can access them at a time. This won't conflict with the interests of the multi-threaded implementation either, because the locked-out thread still won't block the thread that created them, but they will just sit and wait patiently, only blocking code on itself. That's all well beyond the scope of this section, however, but be aware that it's available and probably worth looking into, if you're going to be using synchronicity-sensitive visitors.

Cost
This pattern is flexible enough not to block you. At worst, you will need to spend time thinking about how to solve problems, but this pattern will never block you.

Creation
This pattern is expensive to create, if your code already exists.

Maintenance
It is easy to adapt the code with this pattern, even if there are new links between the item visits.

Removal
This pattern can be removed using refactoring operations from your IDE.

Advises

 * Use the visitor and visit term to indicate the use of the pattern to the other developers.
 * If you have and will always have only one visitor, you'd rather implement the composite pattern.

Implementations
The following example is an example in the C# programming language:

The following example is in the D programming language:

The following example is in the Java programming language:

The following example is an example in the Scala programming language:

Output: No sql representation = price: { &gt: 12 } Sql representation = WHERE price > 12

}}

Patrons de conception/Visiteur