Design Patterns Visitor SE516 Melisa Tyira A design pattern describes a solution to a design problem that can be used over and over again. The key to the goal of a design pattern is the reuse of objects in order to avoid rework. The use of existing objects is a major factor towards software productivity.

A design pattern is described using the following elements: pattern name, problem, solution, and consequences. A pattern name is given to each design pattern in order to increase our vocabulary thus being able to discuss design patterns freely without having to give a description each time. The problem is a description of the design problem, which also leads to a description of when to apply the pattern. The solution is not a description of a specific design that will solve the problem but a description of the elements and interactions between these elements that make up the design. The consequences are the positive and negative results of applying a design pattern. It is beneficial to decide the pros and cons of applying a design pattern in order to determine if there are truly benefits to applying a design pattern.

There are many documented design patterns and groups of these design patterns are related in some way to one another. These groups of design patterns are: creational patterns, structural patterns, and behavioral patterns. I will discuss the Visitor design pattern, which is classified as a behavioral pattern. There are two types of behavioral patterns: behavioral class patterns and behavioral object patterns. Behavioral class patterns are concerned with how objects and classes communicate and their pattern of communication between them. Behavior is distributed among classes by inheritance.

Behavioral object patterns are not concerned with inheritance but are concerned with object composition. Some behavioral object patterns describe how objects work together

2 to perform a task while others encapsulate the behavior in one single object and other objects interact with this object. Visitor is a behavioral object pattern that encapsulates behavior instead of distributing among classes.

Visitor encapsulates an operation to be performed on elements of an object structure and this pattern enables you to define an operation without changing the classes that it operates on. Visitor makes adding new operations easy. When a new visitor is added, new operations are also added. In doing this, the operation being performed on a structure can be changed without changing the classes of elements being operated on.

Consider the example of a department of employees (including manager and engineers). An outside consultant or finance executive occasionally come to meet with the employees in the department. The consultant and finance executive are considered to be visitors. The visitors are escorted to each cubicle and while being escorted, they do not perform any action. Once they arrive at the proper cubicle, they act as needed with the employees. This example is described in the following diagram:

Department

Client EscortVisitor

Visitor Employee

VisitMgr AcceptVisit VisitEngnr ReceivePay

Consultant FinanceExec Manager Engineer

VisitMgr VisitMgr AcceptVisit AcceptVisit VisitEngnr VisitEngnr ReceivePay ReceivePay

3 The Consultant and Finance Executive correspond to the Visitor.

The Consultant and Finance Executive also correspond to the ConcreteVisitor, but

the purpose of the visit determines the ConcreteVisitor.

The Element corresponds to the office visited.

The employee occupying the office corresponds to the ConcreteElement.

The schedule or agenda of the visit corresponds to the ObjectStructure.

This allows easy addition of new visitors. There is no need to change the classes that the visitor operates on (Employee). This example takes on the form displayed in the following diagram. This is a general display of the Visitor design pattern.

Object Structure Client

Visitor Element

VisitConcreteElementA(ConcreteElementA) Accept(Visitor) VisitConcreteElementB(ConcreteElementB)

ConcreteVisitor1 ConcreteVisitor2 ConcreteElementA ConcreteElementB

VisitConcreteElementA(ConcreteElementA) VisitConcreteElementA(ConcreteElementA) Accept(visitor v) Accept(visitor v) VisitConcreteElementB(ConcreteElementB) VisitConcreteElementB(ConcreteElementB) OperationA() OperationB()

v-> VisitConcreteElementA(this) v-> VisitConcreteElementB(this)

The Visitor must declare an operation for each ConcreteElement class. The

Visitor can access the element directly through its interface.

The ConcreteVisitor implements the operations declared by the Visitor.

4 The Element defines an operation in which a visitor is an argument.

The ConcreteElement implements the operation and takes visitor as an argument.

The Visitor pattern makes it easy to add a new operation. The new operation can be added without changing existing classes by adding a new visitor. The visitor also keeps related operations together and keeps unrelated operations separate. All related operations are contained in a visitor. This simplifies classes and the algorithms defined in the visitor. One of the problems with the visitor design is that it makes adding new

ConcreteElement classes tough. Most of the time, when a new ConcreteElement is added, a new abstract operation needs to be added to Visitor and a corresponding implementation needs to be added in every ConcreteVisitor class.

Composite pattern and Interpreter pattern are both related to the Visitor pattern.

The composite pattern divides objects into tree structures in order to treat individual objects and the composed objects uniformly. The visitor pattern can be applied as an operation over a structure of objects defined by composite. The Interpreter pattern takes a given language and defines a representation for its grammar and interprets the language.

Visitor can be used to provide the interpretation.

As a simple example, the visitor pattern can be described as a taxi company.

When a person calls a taxi company to use their services, they are added to the company’s list. The company dispatches a taxi, which, to the customer, becomes the visitor and the customer accepts the visitor. When the customer enters the taxi (Visitor), the customer is no longer in control of the transportation. This describes a real-world example that makes Visitor easy to understand.

5 Sample Code Abstract Visitor Visitor.java

Concrete Visitor Consultant.java FinanceExec.java

Visitor.java public abstract class Visitor { private String title; public void setTitle(String titleIn) { this.title=titleIn; } public final String getTitle(Employee employee) { return employee.getTitle(); } public void visit(Employee employee) { this.setTitle("Title: " + employee.getTitle()); } } Consultant.java public class Consultant extends Visitor { public void visit(Employee employee) { System.out.println("Thank you for visiting. My name is " + employee.getTitle()); } } FinanceExec.java public class FinancExec extends Visitor { public void visit(Employee employee) { System.out.println("Thank you for visiting. My name is " + employee.getTitle()); } }

6 Element Employee.java

Concrete Element Manager.java Engineer.java

Employee.java public abstract class Employee { public String title; public abstract void accept(Visitor visitor); public final String getTitle() { return this.title; } public void setTitle(String titleIn) { title = titleIn; } } Manager.java public class Manager extends Employee { public Manager(String title) { this.setTitle(title); } public void accept(Visitor visitor) { System.out.println("Accepting Visitor"); } } Engineer.java public class Engineer extends Employee { public Engineer(String title) { this.setTitle(title); } public void accept(Visitor visitor) { System.out.println("Accepting Visitor"); } }

7 TestVisitor.java class TestVisitor { public static void main (String[] args) { Employee manager = new Manager("John Q. Manager"); System.out.println(manager.getTitle() + " has been named as manager."); Visitor consultant = new Consultant(); manager.accept(consultant); System.out.println("Consultant is visiting manager."); consultant.visit(manager);

System.out.println("******************************************************* ******"); Employee engineer = new Engineer("Sal E. Engineer"); System.out.println(engineer.getTitle() + " has been named as engineer."); Visitor financeexec = new FinancExec(); manager.accept(financeexec); System.out.println("Finance Executive is visiting engineer."); financeexec.visit(engineer);

} }

8 References

Gamma, Erich & Helm, Richard & Johnson, Ralph & Vlissides, Design Patterns: Elements of Reusable Object-Oriented Design http://www.agcs.com/supportv2/techpapers/patterns/papers/tutnotes http://www.agcs.com/supportv2/techpapers/patterns/papers/patexamples.htm http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/patterns/tutorial.html

9