473,405 Members | 2,334 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,405 developers and data experts.

Patterns: the Visitor pattern

11,448 Expert 8TB
Greetings,

this week we let go of all that algebraic stuff and concentrate a bit more on
what object oriented programming is all about. Java claims to support OO, so
why not use it? In this week's 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:
Expand|Select|Wrap|Line Numbers
  1. public class Beautiful { ... }
  2. public class Efficient { ... }
  3. 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:
Expand|Select|Wrap|Line Numbers
  1. public class Beautiful implements Visitee { 
  2.     public void whoIsThere(Visitor v) { v.thisIsBeautiful(this); }
  3.     // ...
  4. }
  5. public class Efficient implements Visitee { 
  6.     public void whoIsThere(Visitor v) { v.thisIsEfficient(this); }
  7.     // ...
  8. }
  9. public class Gem implements Visitee { 
  10.     public void whoIsThere(Visitor v) { v.thisIsGem(this); }
  11.     // ...
  12. }
... and you add two simple interfaces:
Expand|Select|Wrap|Line Numbers
  1. public interface Visitee {
  2.     public void whoIsThere(Visitor v);
  3. }
  4. public interface Visitor {
  5.     public void thisIsBeautiful(Beautiful b);
  6.     public void thisIsEfficient(Efficient e);
  7.     public void thisIsGem(Gem g);
  8. }
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:
Expand|Select|Wrap|Line Numbers
  1. public class Fred implements Visitor {
  2.     private Iterator<Visitee> i;
  3.     public Fred(Iterator<Visitee> i) { this.i= i; }
  4.  
  5.     public void especiallyForFred() {
  6.  
  7.         while (i.hasNex()) i.whoIsThere(this);
  8.     }
  9.  
  10.     public void thisIsBeautiful(Beautiful b) {
  11.         // added functionality for Beautiful
  12.         // all specially made for Fred
  13.     }
  14.  
  15.     public void thisIsEfficient(Efficient e) {
  16.         // added functionality for Efficient
  17.         // all specially made for Fred
  18.     }
  19.  
  20.     public void thisIsGem(Gem g) {
  21.         // added functionality for Gem
  22.         // all specially made for Fred
  23.     }
  24. }
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.

See you next time when we talk a bit about Decorators (also called Wrappers)
and what they can do for you.

kind regards,

Jos
Apr 22 '07 #1
1 6483
najort
3
Brilliant, short nad simple - as it should be.
Greate Thanks
Feb 5 '08 #2

Sign in to post your reply or Sign up for a free account.

Similar topics

11
by: FluffyCat | last post by:
In Febraury - April of 2002 I put together in Java examples of all 23 of the classic "Gang Of Four" design patterns for my website. Partly I wanted to get a better understanding of those patterns....
5
by: sd | last post by:
Hi, Hoping someone could provide some direction on how to approach this problem using any GOF patterns. e.g. A project contains a team and a team contains zero or more members, each with a...
12
by: FluffyCat | last post by:
New on November 28, 2005 for www.FluffyCat.com PHP 5 Design Pattern Examples - the Visitor Pattern. In the Visitor pattern, one class calls a function in another class and passes an instance of...
17
by: Merlin | last post by:
Probably there is no right or wrong answer to this but I thought to ask to put my mind at rest. Ok lets say you have a object hierarchy (eg. the Glyph in Lexi from GOF book) and you want to use the...
12
by: Jeff | last post by:
I'm just getting up to speed on OOP patterns (e.g, MVC) and I'm wondering how closely they are followed out in the real world. Do those of you who use them try to follow them as closely as possible...
12
by: Jean-pierre Martineau | last post by:
how apply design patterns to c ?
0
by: JosAH | last post by:
Greetings, last week we talked a bit about the Visitor design pattern. This week we'll talk a bit about additional functionality that is sometimes wanted, i.e. the functionality is optional....
0
weaknessforcats
by: weaknessforcats | last post by:
Design Patterns: Visitor Introduction Polymorphism requires a class hierarchy where the interface to the hierarchy is in the base class. Virtual functions allow derived classes to override base...
3
by: aaragon | last post by:
Hello everyone, I've been trying to work with the visitor design pattern, and it works fine except for the following. Let's suppose that we have a fixed hierarchy of classes (many of them)...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.