View RSS Feed

JosAH's blog

The Visitor pattern

Rate this Entry
by , 07-23-2011 at 02:35 PM (2182 Views)
Greetings,

Java claims to support OO, so why not use it? In this article we're going to talk a bit about when and why to apply certain patterns. We'll start with the Visitor pattern. The pattern is also named 'double dispatch' which will become clear near the end of this little article. Here's the story:

Suppose some time ago you wrote a bunch of beautiful, efficient classes; they're real gems. For the sake of this article let's use the following classes:

Java Code:
public class Beautiful { ... }
public class Efficient { ... }
public class Gem { ... }
There's no need to write more of those classes and there's no need to add more functionality to them; users always use your class objects in collections; they traverse the collections and call the fine functionality of the objects in those collections. An ideal solution.

Until one sad day a customer shows up, loaded with money and willing to pay and he wants some additional functionality added to your classes. He already uses your classes and he's very happy with them: he thinks they're very efficient, beautiful and real gems. but ... he wants a bit of functionality added to them. Let's call this customer Fred.

You do like the money Fred is willing to pay and you start adding the wanted functionality and you're doing quite fine until the next sad day Barney comes in at your office and he wants some additional functionality too. Above all he's willing to pay the money for it also. Happy to oblige you tell Barney that you're working on additional functionality for customer Fred too at that very moment and you're willing to accept the task of course.

Barney isn't charmed by the idea: he doesn't like Fred's added functionality in his version of the updated classes at all and he isn't willing to pay for it either. You decide that two different versions of your efficient, beautiful gems of classes isn't that bad and the money isn't bad either.

That night you've got a nightmare: Wilma, Betty, Pebbles, Bambam and even Dino enter your office and they all want some additional functionality added to your fine classes too. A maintenance nightmare rears its ugly head.

What to do? You don't want seven versions of your classes and maybe entire Bedrock wants additional functionality added to your classes, all different.

Then you wake up and find the solution: instead of implementing more and more versions of your fine classes you do this:

Java Code:
public class Beautiful implements Visitee { 
	public void whoIsThere(Visitor v) { v.thisIsBeautiful(this); }
	// ...
}
public class Efficient implements Visitee { 
	public void whoIsThere(Visitor v) { v.thisIsEfficient(this); }
	// ...
}
public class Gem implements Visitee { 
	public void whoIsThere(Visitor v) { v.thisIsGem(this); }
	// ...
}
... and you add two simple interfaces:

Java Code:
public interface Visitee {
	public void whoIsThere(Visitor v);
}
public interface Visitor {
	public void thisIsBeautiful(Beautiful b);
	public void thisIsEfficient(Efficient e);
	public void thisIsGem(Gem g);
}
Your class structure (Beautiful, Efficient and Gem) stays the same; that much you know and you only added one little method to each class and you've defined two interfaces. That's all you did.

Let's implement the functionality for customer Fred; you still have to implement it because you've accepted the money, but now you can implement the functionality in a separate class: the Fred class; you give it an Iterator over all the objects in Fred's collection and implement the functionality like this:

Java Code:
public class Fred implements Visitor {
	private Iterator<Visitee> i;
	public Fred(Iterator<Visitee> i) { this.i= i; }

	public void especiallyForFred() {

		while (i.hasNex()) i.whoIsThere(this);
	}

	public void thisIsBeautiful(Beautiful b) {
		// added functionality for Beautiful
		// all specially made for Fred
	}

	public void thisIsEfficient(Efficient e) {
		// added functionality for Efficient
		// all specially made for Fred
	}

	public void thisIsGem(Gem g) {
		// added functionality for Gem
		// all specially made for Fred
	}
}
You tell customer Fred that all he has to do is to instantiate a Fred object with an Iterator over his collections and then call the especiallyForFred method. He gets his additional functionality then and there's no need for him (or his programmers) to do anything else.

I think you can imagine what Barney's class will look like. If Wilma, Betty, Bambam, Pebbles and even Dino show up you don't have to alter your fine classes; all you have to do is implement the functionality they want, all in a separate class, just as we did in the example above. Each customer has his own added functionality and neither functionality clashes with other functionalities (you simply don't pass them along to other customers). All that's in your maintenance list now are those separate Visitor classes, one for each customer).

This is what the Visitor pattern is all about: a fixed set of classes or interfaces all used in a fixed manner and additional functionality that has to be implemented for different situations. Your fixed set of classes will be the Visitees and the aditional functionalities will be implemented by the visitors. The modifications needed for the original fine classes are minor (just one little method added that implements the Visitee interface).

Of course the additional functionality still needs to be implemented but you've drawn that away from your original set of classes. And even more: you can add whatever additional functionality on demand without any modification to your original class ad nauseam. On the other hand: the Visitor pattern can only be applied when your set of classes is more or less fixed (you don't want to change those interfaces and previously existing Visitors again and again). But if your set of classes is fixed, go for it: implement Visitors in your existing code base and keep your classes clean. You just have to prepare your classes for Visitors that may not even have been designed and written yet, i.e. your fixed set of classes is prepared for an unknown future.

If you carefully read the example classes and interfaces above you'll notice that the Visitor starts by calling a Visitee; the Visitee responds by calling the appropriate method on the Visitor again. That's the reason why the Visitor pattern is dubbed the 'Double Dispatch' pattern: from Visitor to Visitee and back again. That's all that's needed to keep your classes clean and frees you from maintenance nightmares.

kind regards,

Jos
jlczuk likes this.

Submit "The Visitor pattern" to Facebook Submit "The Visitor pattern" to Digg Submit "The Visitor pattern" to del.icio.us Submit "The Visitor pattern" to StumbleUpon Submit "The Visitor pattern" to Google

Tags: None Add / Edit Tags
Categories
Uncategorized

Comments