0% found this document useful (0 votes)
5 views18 pages

Visitor

The document discusses the Visitor Pattern, a behavioral design pattern that separates algorithms from the objects they operate on, particularly in the context of exporting data from a complex graph structure. It outlines the problem of modifying existing classes for new behaviors, proposes a solution using a separate visitor class, and explains how this approach allows for easier maintenance and extension of functionality. The document includes examples, structure, and pseudocode to illustrate the implementation of the Visitor Pattern.

Uploaded by

tamattack123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views18 pages

Visitor

The document discusses the Visitor Pattern, a behavioral design pattern that separates algorithms from the objects they operate on, particularly in the context of exporting data from a complex graph structure. It outlines the problem of modifying existing classes for new behaviors, proposes a solution using a separate visitor class, and explains how this approach allows for easier maintenance and extension of functionality. The document includes examples, structure, and pseudocode to illustrate the implementation of the Visitor Pattern.

Uploaded by

tamattack123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

HaQT Object-Oriented Programming

Visitor Pattern

Contents
1 Intent 2

2 Problem 2

3 Solution 3

4 Real-World Analogy 5

5 Structure 6

6 Pseudocode 7

7 Applicability 9

8 How to Implement 10

9 Pros and Cons 10

10 Relations with Other Patterns 11

11 Examples 11
11.1 Without Visitor Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
11.2 Using Visitor Patterns: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

12 Exercises 18

1
HaQT Object-Oriented Programming

1 Intent
Visitor is a behavioral design pattern that lets you separate algorithms from the objects on
which they operate.

2 Problem
Imagine that your team develops an app which works with geographic information structured
as one colossal graph. Each node of the graph may represent a complex entity such as a city,
but also more granular things like industries, sightseeing areas, etc. The nodes are connected
with others if there’s a road between the real objects that they represent. Under the hood,
each node type is represented by its own class, while each specific node is an object.

Exporting the graph into XML.

At some point, you got a task to implement exporting the graph into XML format. At
first, the job seemed pretty straightforward. You planned to add an export method to each

2
HaQT Object-Oriented Programming

node class and then leverage recursion to go over each node of the graph, executing the
export method. The solution was simple and elegant: thanks to polymorphism, you weren’t
coupling the code which called the export method to concrete classes of nodes.
Unfortunately, the system architect refused to allow you to alter existing node classes. He
said that the code was already in production and he didn’t want to risk breaking it because
of a potential bug in your changes.

The XML export method had to be added into all node classes, which bore the risk of
breaking the whole application if any bugs slipped through along with the change.

Besides, he questioned whether it makes sense to have the XML export code within the
node classes. The primary job of these classes was to work with geodata. The XML export
behavior would look alien there.
There was another reason for the refusal. It was highly likely that after this feature was
implemented, someone from the marketing department would ask you to provide the ability
to export into a different format, or request some other weird stuff. This would force you to
change those precious and fragile classes again.

3 Solution
The Visitor pattern suggests that you place the new behavior into a separate class called
visitor, instead of trying to integrate it into existing classes. The original object that had to
perform the behavior is now passed to one of the visitor’s methods as an argument, providing
the method access to all necessary data contained within the object.
Now, what if that behavior can be executed over objects of different classes? For example, in
our case with XML export, the actual implementation will probably be a little bit different
across various node classes. Thus, the visitor class may define not one, but a set of methods,
each of which could take arguments of different types, like this:

3
HaQT Object-Oriented Programming

1 c l a s s E x p o r t V i s i t o r implements V i s i t o r i s
method doForCity ( City c ) { . . . }
3 method d o F o r I n d u s t r y ( I n d u s t r y f ) { . . . }
method d o F o r S i g h t S e e i n g ( S i g h t S e e i n g s s ) { . . . }
5 // . . .

But how exactly would we call these methods, especially when dealing with the whole graph?
These methods have different signatures, so we can’t use polymorphism. To pick a proper
visitor method that’s able to process a given object, we’d need to check its class. Doesn’t
this sound like a nightmare?

1 f o r e a c h ( Node node i n graph )


i f ( node i n s t a n c e o f City )
3 e x p o r t V i s i t o r . doForCity ( ( City ) node )
i f ( node i n s t a n c e o f I n d u s t r y )
5 e x p o r t V i s i t o r . d o F o r I n d u s t r y ( ( I n d u s t r y ) node )
// . . .
7 }

You might ask, why don’t we use method overloading? That’s when you give all methods the
same name, even if they support different sets of parameters. Unfortunately, even assuming
that our programming language supports it at all (as Java and C# do), it won’t help us.
Since the exact class of a node object is unknown in advance, the overloading mechanism
won’t be able to determine the correct method to execute. It’ll default to the method that
takes an object of the base Node class.
However, the Visitor pattern addresses this problem. It uses a technique called Double
Dispatch, which helps to execute the proper method on an object without cumbersome
conditionals. Instead of letting the client select a proper version of the method to call, how
about we delegate this choice to objects we’re passing to the visitor as an argument? Since
the objects know their own classes, they’ll be able to pick a proper method on the visitor
less awkwardly. They “accept” a visitor and tell it what visiting method should be executed.

1 // C l i e n t code
f o r e a c h ( Node node i n graph )
3 node . a c c e p t ( e x p o r t V i s i t o r )

5 // City
c l a s s City i s
7 method a c c e p t ( V i s i t o r v ) i s
v . doForCity ( t h i s )

4
HaQT Object-Oriented Programming

9 // . . .

11 // I n d u s t r y
c l a s s Industry i s
13 method a c c e p t ( V i s i t o r v ) i s
v . doForIndustry ( t h i s )
15 // . . .

I confess. We had to change the node classes after all. But at least the change is trivial and
it lets us add further behaviors without altering the code once again.
Now, if we extract a common interface for all visitors, all existing nodes can work with any
visitor you introduce into the app. If you find yourself introducing a new behavior related
to nodes, all you have to do is implement a new visitor class.

4 Real-World Analogy

A good insurance agent is always ready to offer different policies to


various types of organizations.

Imagine a seasoned insurance agent who’s eager to get new customers. He can visit every
building in a neighborhood, trying to sell insurance to everyone he meets. Depending on the
type of organization that occupies the building, he can offer specialized insurance policies:

• If it’s a residential building, he sells medical insurance.

• If it’s a bank, he sells theft insurance.

• If it’s a coffee shop, he sells fire and flood insurance.

5
HaQT Object-Oriented Programming

5 Structure

Structure of Visitor Pattern.

1. The Visitor interface declares a set of visiting methods that can take concrete elements
of an object structure as arguments. These methods may have the same names if
the program is written in a language that supports overloading, but the type of their
parameters must be different.
2. Each Concrete Visitor implements several versions of the same behaviors, tailored for
different concrete element classes.
3. The Element interface declares a method for "accepting" visitors. This method should
have one parameter declared with the type of the visitor interface.
4. Each Concrete Element must implement the acceptance method. The purpose of this
method is to redirect the call to the proper visitor’s method corresponding to the
current element class. Be aware that even if a base element class implements this
method, all subclasses must still override this method in their own classes and call the
appropriate method on the visitor object.

6
HaQT Object-Oriented Programming

5. The Client usually represents a collection or some other complex object (for example,
a Composite tree). Usually, clients aren’t aware of all the concrete element classes
because they work with objects from that collection via some abstract interface.

6 Pseudocode
In this example, the Visitor pattern adds XML export support to the class hierarchy of
geometric shapes.

Exporting various types of objects into XML format via a visitor object.

1 // The e l e m e n t i n t e r f a c e d e c l a r e s an ‘ a c c e p t ‘ method t h a t t a k e s
// t h e b a s e v i s i t o r i n t e r f a c e a s an argument .
3 i n t e r f a c e Shape i s
method move ( x , y )
5 method draw ( )
method a c c e p t ( v : V i s i t o r )
7

7
HaQT Object-Oriented Programming

9 // Each c o n c r e t e e l e m e n t c l a s s must implement t h e ‘ a c c e p t ‘


// method i n such a way t h a t i t c a l l s t h e v i s i t o r ’ s method t h a t
11 // c o r r e s p o n d s t o t h e e l e m e n t ’ s c l a s s .
c l a s s Dot implements Shape i s
13 // . . .

15 // Note t h a t we ’ r e c a l l i n g ‘ v i s i t D o t ‘ , which matches t h e


// c u r r e n t c l a s s name . This way we l e t t h e v i s i t o r know t h e
17 // c l a s s o f t h e e l e m e n t i t works with .
method a c c e p t ( v : V i s i t o r ) i s
19 v . visitDot ( this )

21
c l a s s C i r c l e implements Shape i s
23 // . . .
method a c c e p t ( v : V i s i t o r ) i s
25 v. visitCircle ( this )

27
c l a s s R e c t a n g l e implements Shape i s
29 // . . .
method a c c e p t ( v : V i s i t o r ) i s
31 v . visitRectangle ( this )

33
c l a s s CompoundShape implements Shape i s
35 // . . .
method a c c e p t ( v : V i s i t o r ) i s
37 v . visitCompoundShape ( t h i s )

39
// The V i s i t o r i n t e r f a c e d e c l a r e s a s e t o f v i s i t i n g methods t h a t
41 // c o r r e s p o n d t o e l e m e n t c l a s s e s . The s i g n a t u r e o f a v i s i t i n g method
// l e t s t h e v i s i t o r i d e n t i f y t h e e x a c t c l a s s o f t h e e l e m e n t t h a t
43 // i t ’ s d e a l i n g with .
interface Visitor is
45 method v i s i t D o t ( d : Dot )
method v i s i t C i r c l e ( c : C i r c l e )
47 method v i s i t R e c t a n g l e ( r : R e c t a n g l e )
method visitCompoundShape ( c s : CompoundShape )
49
// C o n c r e t e v i s i t o r s implement s e v e r a l v e r s i o n s o f t h e same
51 // a l g o r i t h m , which can work with a l l c o n c r e t e e l e m e n t c l a s s e s .
//
53 // You can e x p e r i e n c e t h e b i g g e s t b e n e f i t o f t h e V i s i t o r p a t t e r n
// when u s i n g i t with a complex o b j e c t s t r u c t u r e such a s a
55 // Composite t r e e . In t h i s c a s e , i t might be h e l p f u l t o s t o r e
// some i n t e r m e d i a t e s t a t e o f t h e a l g o r i t h m w h i l e e x e c u t i n g t h e
57 // v i s i t o r ’ s methods o v e r v a r i o u s o b j e c t s o f t h e s t r u c t u r e .
c l a s s XMLExportVisitor implements V i s i t o r i s
59 method v i s i t D o t ( d : Dot ) i s
// Export t h e dot ’ s ID and c e n t e r c o o r d i n a t e s .

8
HaQT Object-Oriented Programming

61
method v i s i t C i r c l e ( c : C i r c l e ) i s
63 // Export t h e c i r c l e ’ s ID , c e n t e r c o o r d i n a t e s and r a d i u s .

65 method v i s i t R e c t a n g l e ( r : R e c t a n g l e ) i s
// Export t h e r e c t a n g l e ’ s ID , l e f t −top c o o r d i n a t e s , width and h e i g h t .
67
method visitCompoundShape ( c s : CompoundShape ) i s
69 // Export t h e shape ’ s ID a s w e l l a s t h e l i s t o f i t s c h i l d r e n ’ s IDs .

71
// The c l i e n t code can run v i s i t o r o p e r a t i o n s o v e r any s e t o f
73 // e l e m e n t s w i t h o u t f i g u r i n g out t h e i r c o n c r e t e c l a s s e s . The
// a c c e p t o p e r a t i o n d i r e c t s a c a l l t o t h e a p p r o p r i a t e o p e r a t i o n
75 // i n t h e v i s i t o r o b j e c t .
c l a s s Application i s
77 f i e l d a l l S h a p e s : a r r a y o f Shapes

79 method e x p o r t ( ) i s
e x p o r t V i s i t o r = new XMLExportVisitor ( )
81

f o r e a c h ( shape i n a l l S h a p e s ) do
83 shape . a c c e p t ( e x p o r t V i s i t o r )

If you wonder why we need the accept method in this example, my article Visitor and Double
Dispatch addresses this question in detail.

7 Applicability
• Use the Visitor when you need to perform an operation on all elements of
a complex object structure (for example, an object tree).

▷ The Visitor pattern lets you execute an operation over a set of objects with different
classes by having a visitor object implement several variants of the same operation,
which correspond to all target classes.

• Use the Visitor to clean up the business logic of auxiliary behaviors.

▷ The pattern lets you make the primary classes of your app more focused on their main
jobs by extracting all other behaviors into a set of visitor classes.

• Use the pattern when a behavior makes sense only in some classes of a class
hierarchy, but not in others.

▷ You can extract this behavior into a separate visitor class and implement only those
visiting methods that accept objects of relevant classes, leaving the rest empty.

9
HaQT Object-Oriented Programming

8 How to Implement
1. Declare the visitor interface with a set of “visiting” methods, one per each concrete
element class that exists in the program.

2. Declare the element interface. If you’re working with an existing element class hier-
archy, add the abstract “acceptance” method to the base class of the hierarchy. This
method should accept a visitor object as an argument.

3. Implement the acceptance methods in all concrete element classes. These methods
must simply redirect the call to a visiting method on the incoming visitor object which
matches the class of the current element.

4. The element classes should only work with visitors via the visitor interface. Visitors,
however, must be aware of all concrete element classes, referenced as parameter types
of the visiting methods.

5. For each behavior that can’t be implemented inside the element hierarchy, create a
new concrete visitor class and implement all of the visiting methods.
You might encounter a situation where the visitor will need access to some private
members of the element class. In this case, you can either make these fields or methods
public, violating the element’s encapsulation, or nest the visitor class in the element
class. The latter is only possible if you’re lucky to work with a programming language
that supports nested classes.

6. The client must create visitor objects and pass them into elements via "acceptance"
methods.

9 Pros and Cons


+ Open/Closed Principle. You can introduce a new behavior that can work with objects
of different classes without changing these classes.

+ Single Responsibility Principle. You can move multiple versions of the same behavior
into the same class.

+ A visitor object can accumulate some useful information while working with various ob-
jects. This might be handy when you want to traverse some complex object structure,
such as an object tree, and apply the visitor to each object of this structure.

- You need to update all visitors each time a class gets added to or removed from the
element hierarchy.

- Visitors might lack the necessary access to the private fields and methods of the ele-
ments that they’re supposed to work with.

10
HaQT Object-Oriented Programming

10 Relations with Other Patterns


• You can treat Visitor as a powerful version of the Command pattern. Its objects can
execute operations over various objects of different classes.

• You can use Visitor to execute an operation over an entire Composite tree.

• You can use Visitor along with Iterator to traverse a complex data structure and
execute some operation over its elements, even if they all have different classes.

11 Examples
11.1 Without Visitor Pattern

1 public i n t e r f a c e MailClient {
v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) ;
3 void receiveMail ( String [ ] mailInfo ) ;
boolean configureForMac ( ) ;
5 b o o l e a n configureForWindows ( ) ;
}

p u b l i c c l a s s O p e r a M a i l C l i e n t implements M a i l C l i e n t {
2
@Override
4 p u b l i c v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) {
System . out . p r i n t l n ( " O p e r a M a i l C l i e n t : Sending m a i l " ) ;
6 }

8 @Override
public void receiveMail ( String [ ] mailInfo ) {
10 System . out . p r i n t l n ( " O p e r a M a i l C l i e n t : R e c e i v i n g m a i l " ) ;
}
12
@Override
14 p u b l i c boolean configureForMac ( ) {
System . out . p r i n t l n ( "Configuration of Opera mail client for Mac complete" ) ;
16 return true ;
}
18
@Override
20 p u b l i c b o o l e a n configureForWindows ( ) {
System . out . p r i n t l n ( "Configuration of Opera mail client for Windows complete" ) ;
22 return true ;
}

11
HaQT Object-Oriented Programming

1 p u b l i c c l a s s S q u i r r e l M a i l C l i e n t implements M a i l C l i e n t {

3 @Override
p u b l i c v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) {
5 System . out . p r i n t l n ( " S q u i r r e l M a i l C l i e n t : Sending m a i l " ) ;
}
7
@Override
9 public void receiveMail ( String [ ] mailInfo ) {
System . out . p r i n t l n ( " S q u i r r e l M a i l C l i e n t : R e c e i v i n g m a i l " ) ;
11 }

13 @Override
p u b l i c boolean configureForMac ( ) {
15 System . out . p r i n t l n ( "Configuration of Squirrel mail client for Mac complete" ) ;
return true ;
17 }

19 @Override
p u b l i c b o o l e a n configureForWindows ( ) {
21 System . out . p r i n t l n ( "Configuration of Squirrel mail client for Windows complete" ) ;
return true ;
23 }
}

public c l a s s MailClientTest {
2
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n {
4 testConfigureMailClientForDifferentEnvironments () ;
}
6

public void testConfigureMailClientForDifferentEnvironments ( ) {


8 M a i l C l i e n t o p e r a M a i l C l i e n t = new O p e r a M a i l C l i e n t ( ) ;
operaMailClient . configureForMac ( ) ;
10 o p e r a M a i l C l i e n t . configureForWindows ( ) ;

12 M a i l C l i e n t s q u i r r e l M a i l C l i e n t = new S q u i r r e l M a i l C l i e n t ( ) ;
s q u i r r e l M a i l C l i e n t . configureForMac ( ) ;
14 s q u i r r e l M a i l C l i e n t . configureForWindows ( ) ;
}
16 }

12
HaQT Object-Oriented Programming

11.2 Using Visitor Patterns:

package com . p a t t e r n s . v i s i t o r . s t r u c t u r e ;
2

import com . p a t t e r n s . v i s i t o r . v i s i t o r s . M a i l C l i e n t V i s i t o r ;
4
public i n t e r f a c e MailClient {
6 v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) ;
void receiveMail ( String [ ] mailInfo ) ;
8 boolean accept ( M a i l C l i e n t V i s i t o r v i s i t o r ) ;
}

1 package com . p a t t e r n s . v i s i t o r . s t r u c t u r e ;

3 import com . p a t t e r n s . v i s i t o r . v i s i t o r s . M a i l C l i e n t V i s i t o r ;

5 p u b l i c c l a s s O p e r a M a i l C l i e n t implements M a i l C l i e n t {
@Override
7 p u b l i c v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) {
System . out . p r i n t l n ( " O p e r a M a i l C l i e n t : Sending m a i l " ) ;
9 }

11 @Override
public void receiveMail ( String [ ] mailInfo ) {
13 System . out . p r i n t l n ( " O p e r a M a i l C l i e n t : R e c e i v i n g m a i l " ) ;
}
15
@Override
17 public boolean accept ( M a i l C l i e n t V i s i t o r v i s i t o r ) {
visitor . visit ( this ) ;
19 return true ;
}
21 }

1 package com . p a t t e r n s . v i s i t o r . s t r u c t u r e ;

3 import com . p a t t e r n s . v i s i t o r . v i s i t o r s . M a i l C l i e n t V i s i t o r ;

5 p u b l i c c l a s s S q u i r r e l M a i l C l i e n t implements M a i l C l i e n t {
@Override
7 p u b l i c v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) {
System . out . p r i n t l n ( " S q u i r r e l M a i l C l i e n t : Sending m a i l " ) ;
9 }

13
HaQT Object-Oriented Programming

11 @Override
public void receiveMail ( String [ ] mailInfo ) {
13 System . out . p r i n t l n ( " S q u i r r e l M a i l C l i e n t : R e c e i v i n g m a i l " ) ;
}
15
@Override
17 public boolean accept ( M a i l C l i e n t V i s i t o r v i s i t o r ) {
visitor . visit ( this ) ;
19 return true ;
}
21 }

1 package com . p a t t e r n s . v i s i t o r . s t r u c t u r e ;

3 import com . p a t t e r n s . v i s i t o r . v i s i t o r s . M a i l C l i e n t V i s i t o r ;

5 p u b l i c c l a s s Z i m b r a M a i l C l i e n t implements M a i l C l i e n t {
@Override
7 p u b l i c v o i d sendMail ( S t r i n g [ ] m a i l I n f o ) {
System . out . p r i n t l n ( " Z i m b r a M a i l C l i e n t : Sending m a i l " ) ;
9 }

11 @Override
public void receiveMail ( String [ ] mailInfo ) {
13 System . out . p r i n t l n ( " Z i m b r a M a i l C l i e n t : R e c e i v i n g m a i l " ) ;
}
15
@Override
17 public boolean accept ( M a i l C l i e n t V i s i t o r v i s i t o r ) {
visitor . visit ( this ) ;
19 return true ;
}
21 }

1 package com . p a t t e r n s . v i s i t o r . v i s i t o r s ;

3 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . O p e r a M a i l C l i e n t ;
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . S q u i r r e l M a i l C l i e n t ;
5 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . Z i m b r a M a i l C l i e n t ;

7 public interface MailClientVisitor {


void v i s i t ( OperaMailClient mailClient ) ;
9 void v i s i t ( SquirrelMailClient mailClient ) ;
void v i s i t ( ZimbraMailClient mailClient ) ;
11 }

14
HaQT Object-Oriented Programming

1 package com . p a t t e r n s . v i s i t o r . v i s i t o r s ;

3 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . O p e r a M a i l C l i e n t ;
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . S q u i r r e l M a i l C l i e n t ;
5 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . Z i m b r a M a i l C l i e n t ;

7 p u b l i c c l a s s W i n d o w s M a i l C l i e n t V i s i t o r implements M a i l C l i e n t V i s i t o r {
@Override
9 public void v i s i t ( OperaMailClient mailClient ) {
System . out . p r i n t l n ( "Configuration of Opera mail client for Windows complete" ) ;
11 }

13 @Override
public void v i s i t ( S q u i r r e l M a i l C l i e n t mailClient ) {
15 System . out . p r i n t l n ( "Configuration of Squirrel mail client for Windows complete" ) ;
}
17
@Override
19 public void v i s i t ( ZimbraMailClient mailClient ) {
System . out . p r i n t l n ( "Configuration of Zimbra mail client for Windows complete" ) ;
21 }
}

package com . p a t t e r n s . v i s i t o r . v i s i t o r s ;
2
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . O p e r a M a i l C l i e n t ;
4 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . S q u i r r e l M a i l C l i e n t ;
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . Z i m b r a M a i l C l i e n t ;
6
p u b l i c c l a s s M a c M a i l C l i e n t V i s i t o r implements M a i l C l i e n t V i s i t o r {
8 @Override
public void v i s i t ( OperaMailClient mailClient ) {
10 System . out . p r i n t l n ( "Configuration of Opera mail client for Mac complete" ) ;
}
12
@Override
14 public void v i s i t ( S q u i r r e l M a i l C l i e n t mailClient ) {
System . out . p r i n t l n ( "Configuration of Squirrel mail client for Mac complete" ) ;
16 }

18 @Override
public void v i s i t ( ZimbraMailClient mailClient ) {
20 System . out . p r i n t l n ( "Configuration of Zimbra mail client for Mac complete" ) ;
}
22 }

15
HaQT Object-Oriented Programming

package com . p a t t e r n s . v i s i t o r . v i s i t o r s ;
2
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . O p e r a M a i l C l i e n t ;
4 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . S q u i r r e l M a i l C l i e n t ;
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . Z i m b r a M a i l C l i e n t ;
6

p u b l i c c l a s s L i n u x M a i l C l i e n t V i s i t o r implements M a i l C l i e n t V i s i t o r {
8 @Override
public void v i s i t ( OperaMailClient mailClient ) {
10 System . out . p r i n t l n ( "Configuration of Opera mail client for Linux complete" ) ;
}
12

@Override
14 public void v i s i t ( S q u i r r e l M a i l C l i e n t mailClient ) {
System . out . p r i n t l n ( "Configuration of Squirrel mail client for Linux complete" ) ;
16 }

18 @Override
public void v i s i t ( ZimbraMailClient mailClient ) {
20 System . out . p r i n t l n ( "Configuration of Zimbra mail client for Linux complete" ) ;
}
22 }

package com . p a t t e r n s . v i s i t o r . v i s i t o r s ;
2
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . O p e r a M a i l C l i e n t ;
4 import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . S q u i r r e l M a i l C l i e n t ;
import com . p a t t e r n s . v i s i t o r . s t r u c t u r e . Z i m b r a M a i l C l i e n t ;
6
public class MailClientVisitorTest {
8 private MacMailClientVisitor macVisitor ;
private LinuxMailClientVisitor linuxVisitor ;
10 private WindowsMailClientVisitor windowsVisitor ;
p r i v a t e OperaMailClient operaMailClient ;
12 private SquirrelMailClient squirrelMailClient ;
p r i v a t e ZimbraMailClient zimbraMailClient ;
14

p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
16 setup () ;

18 testOperaMailClient () ;
testSquirrelMailClient () ;
20 testZimbraMailClient ()
}
22
public void setup ( ) {
24 m a c V i s i t o r = new M a c M a i l C l i e n t V i s i t o r ( ) ;
l i n u x V i s i t o r = new L i n u x M a i l C l i e n t V i s i t o r ( ) ;

16
HaQT Object-Oriented Programming

26 w i n d o w s V i s i t o r = new W i n d o w s M a i l C l i e n t V i s i t o r ( ) ;
o p e r a M a i l C l i e n t = new O p e r a M a i l C l i e n t ( ) ;
28 s q u i r r e l M a i l C l i e n t = new S q u i r r e l M a i l C l i e n t ( ) ;
z i m b r a M a i l C l i e n t = new Z i m b r a M a i l C l i e n t ( ) ;
30 }

32 p u b l i c v o i d t e s t O p e r a M a i l C l i e n t ( ) throws E x c e p t i o n {
System . out . p r i n t l n ( "—–Testing Opera Mail Client for different environments—–" ) ;
34 operaMailClient . accept ( macVisitor ) ;
operaMailClient . accept ( l i n u x V i s i t o r ) ;
36 operaMailClient . accept ( windowsVisitor ) ;
}
38
p u b l i c v o i d t e s t S q u i r r e l M a i l C l i e n t ( ) throws E x c e p t i o n {
40 System . out . p r i n t l n ( " \n—Testing Squirrel Mail Client for different environments—" ) ;
s q u i r r e l M a i l C l i e n t . accept ( macVisitor ) ;
42 s qu ir r el Ma i lC li e nt . accept ( l i n u x V i s i t o r ) ;
s q u i r r e l M a i l C l i e n t . accept ( windowsVisitor ) ;
44 }

46 p u b l i c v o i d t e s t Z i m b r a M a i l C l i e n t ( ) throws E x c e p t i o n {
System . out . p r i n t l n ( " \n—–Testing Zimbra Mail Client for different environments—–" ) ;
48 zimbraMailClient . accept ( macVisitor ) ;
zimbraMailClient . accept ( l i n u x V i s i t o r ) ;
50 zimbraMailClient . accept ( windowsVisitor ) ;
}
52 }

Command window

- - - -−T e s t i n g Opera Mail C l i e n t f o r d i f f e r e n t e n v i r o n m e n t s - - - -−


2 C o n f i g u r a t i o n o f Opera m a i l c l i e n t f o r Mac c o m p l e t e
C o n f i g u r a t i o n o f Opera m a i l c l i e n t f o r Linux c o m p l e t e
4 C o n f i g u r a t i o n o f Opera m a i l c l i e n t f o r Windows c o m p l e t e

6 - - - -−T e s t i n g S q u i r r e l Mail C l i e n t f o r d i f f e r e n t e n v i r o n m e n t s - - - -−
Configuration of S q u i r r e l mail c l i e n t f o r Mac c o m p l e t e
8 Configuration of S q u i r r e l mail c l i e n t f o r Linux c o m p l e t e
Configuration of S q u i r r e l mail c l i e n t f o r Windows c o m p l e t e
10
- - - -−T e s t i n g Zimbra Mail C l i e n t f o r d i f f e r e n t e n v i r o n m e n t s - - - -−
12 C o n f i g u r a t i o n o f Zimbra m a i l c l i e n t f o r Mac c o m p l e t e
C o n f i g u r a t i o n o f Zimbra m a i l c l i e n t f o r Linux c o m p l e t e
14 C o n f i g u r a t i o n o f Zimbra m a i l c l i e n t f o r Windows c o m p l e t e

17
HaQT Object-Oriented Programming

12 Exercises
1. Write a program that uses the Visitor Pattern as shown in the following uml diagram.

2. Write a program that uses the Visitor Pattern as shown in the following uml diagram.

3. Write code to demonstrate the program from the pseudocode.

18

You might also like