Design Pattern

Visitor Pattern Design Patterns in Java

This article explains about the visitor pattern of the GoF Design Behavior patterns. In the visitor design pattern, the visitor class is used to alter the algorithm that is executing as part of the element class. This is an easy methodology to control the algorithm executing for elements by using the visitor class, as the executing algorithm varies with the variance in the visitor class.

The Visitor class is considered as a type of Behavior pattern that presents an implementation of the exchange of place with the exchange of control mechanism. As the object of the element, the class must provide a place to the object of the visitor class in order for it to control the element class. The visitor class is the controller of all variance in the operations of the element class.

Visitor Pattern

According to the Gang of Four:

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

UML Class Diagram

Visitor Class

  • The visitor class performs the mechanism of controlling any sort of variance in the element class. The object of the visitor class resides in the element class for control.

Element Class

  • The element class is the main class performing critical operations whose variations are controlled by the visitor class.
  • The operation that is performed on the element is represented through visitor behavioural pattern. A new operation can be defined by the Visitor class without any alteration to the normal classes belonging to the element being operated on. Many operations that are not related to each other are performed on a structure that is composed of heterogeneous node objects which can pollute the classes of the node objects.
  • To avoid pollution, querying is performed on nodes to determine the correct type and point the operation to it. This is quite inefficient as it cost a lot of time and resources for querying every node and waiting for a response. The Visitor Behavioral Pattern provides a solution with this by abstracting functionalities on element objects aggregated together in a hierarchical structure.

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Pattern“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use an author discount to purchase this book by using code- “AUTHDIS40“.

The Element classes are created in such a way that includes only the necessary functionalities and the Visitor subclasses are created that provide the additional functionality for the Element class. A double dispatch mechanism is implemented by the Visitor Class in which, the request’s name and the Visitor type and Element type both act as receivers these things determine the operation that will be performed.

Visitor Design Pattern Implementation

This can be implemented by creating a Visitor hierarchy through the pure virtual class of the visitor. A method visit() is declared in the base class of the Visitor and it is overloaded in the child/derived classes by using the specific methodology of querying and casting. The visitor() method receives the pointer to the derived class for the Element class. The base class of the Element class has an accept() method which accepts the pointer to the base class of the Visitor class. The accept() method can be implemented on the Element’s concrete derived class by calling the visit() method on the Visitor’s derived instance.

The accept() method is responsible for the selection of the Element class to be controlled and the visit() method allocated the control to the correct Visitor instance. This allows related and unrelated operations to be performed on an object that is aggregated into a single hierarchical structure.

Visitor Pattern Sample Example

In this sample real-world example, we demonstrate the Visitor pattern in which two objects traverse a list of Employees and perform the same operation on each Employee. There are two visitor objects define different operations. These operations are one adjusts vacation days and the other income.

VisitorPatternDemo, our demo class, will use Employee and Visitor classes to demonstrate the use of visitor pattern.

Step 1: Define an interface to represent element.
Element.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public interface Element {
	
	void accept(IVisitor visitor);
}

Step 2: Create concrete classes extending the above class.
Employee.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class Employee implements Element {
	
	private String _name;
    private double _income;
    private int _vacationDays;
    
    
	public Employee(String _name, double _income, int _vacationDays) {
		super();
		this._name = _name;
		this._income = _income;
		this._vacationDays = _vacationDays;
	}

	@Override
	public void accept(IVisitor visitor) {
		visitor.visit(this);
	}

	public String get_name() {
		return _name;
	}

	public void set_name(String _name) {
		this._name = _name;
	}

	public double get_income() {
		return _income;
	}

	public void set_income(double _income) {
		this._income = _income;
	}

	public int get_vacationDays() {
		return _vacationDays;
	}

	public void set_vacationDays(int _vacationDays) {
		this._vacationDays = _vacationDays;
	}
	
}

Director.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class Director extends Employee {

	public Director() {
		super("Anamika", 45000.0, 20);
	}

}

President.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class President extends Employee {

	public President() {
		super("Arnav", 65000.0, 25);
	}

}

Clerk.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class Clerk extends Employee {

	public Clerk() {
		super("Dinesh", 35000.0, 18);
	}

}

Employees.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Dinesh.Rajput
 *
 */
public class Employees {
	
	// Setup employee collection
	List empList = new ArrayList<>();
	
	public void add(Employee employee){
		empList.add(employee);
    }

    public void remove(Employee employee){
    	empList.remove(employee);
    }

    public void accept(IVisitor visitor){
    	for(Employee employee : empList)	{
    		employee.accept(visitor);
    	}
    	System.out.println();
    }
}

Step 3: Define an interface to represent visitor.
IVisitor.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public interface IVisitor {
	
	void visit(Element element);
}

Step 4: Create a concrete visitor implementing the above class.
IncomeVisitor.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class IncomeVisitor implements IVisitor {

	@Override
	public void visit(Element element) {
		Employee employee = (Employee) element;
		// Provide 10% pay raise
		employee.set_income(employee.get_income()*1.10);
		System.out.println(employee.getClass().getSimpleName()+" "+employee.get_name() +"'s new income: "+employee.get_income());
	}
}

VacationVisitor.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class VacationVisitor implements IVisitor {

	@Override
	public void visit(Element element) {
		Employee employee = (Employee) element;
		// Provide 3 extra vacation days
		employee.set_vacationDays(employee.get_vacationDays()+3);
		System.out.println(employee.getClass().getSimpleName()+" "+employee.get_name() +"'s vacation days: "+employee.get_vacationDays());
	}
}

Step 5: VisitorPatternDemo, our demo class, will use Employee and Visitor classes to demonstrate the use of visitor pattern.

VisitorPatternDemo.java

/**
 * 
 */
package com.doj.patterns.behavior.visitor;

/**
 * @author Dinesh.Rajput
 *
 */
public class VisitorPatternDemo {
	
	public static void main(String[] args) {
		
		// Setup employee collection
		Employees employees = new Employees();
		employees.add(new Clerk());
		employees.add(new Director());
		employees.add(new President());
		
		 // Employees are 'visited'
		employees.accept(new IncomeVisitor());
		employees.accept(new VacationVisitor());
	}
}

Step 6: Let’s run this demo class and verify the output.

Clerk Dinesh's new income: 38500.0
Director Anamika's new income: 49500.00000000001
President Arnav's new income: 71500.0

Clerk Dinesh's vacation days: 21
Director Anamika's vacation days: 23
President Arnav's vacation days: 28

Previous
Next
Dinesh Rajput

Dinesh Rajput is the chief editor of a website Dineshonjava, a technical blog dedicated to the Spring and Java technologies. It has a series of articles related to Java technologies. Dinesh has been a Spring enthusiast since 2008 and is a Pivotal Certified Spring Professional, an author of a book Spring 5 Design Pattern, and a blogger. He has more than 10 years of experience with different aspects of Spring and Java design and development. His core expertise lies in the latest version of Spring Framework, Spring Boot, Spring Security, creating REST APIs, Microservice Architecture, Reactive Pattern, Spring AOP, Design Patterns, Struts, Hibernate, Web Services, Spring Batch, Cassandra, MongoDB, and Web Application Design and Architecture. He is currently working as a technology manager at a leading product and web development company. He worked as a developer and tech lead at the Bennett, Coleman & Co. Ltd and was the first developer in his previous company, Paytm. Dinesh is passionate about the latest Java technologies and loves to write technical blogs related to it. He is a very active member of the Java and Spring community on different forums. When it comes to the Spring Framework and Java, Dinesh tops the list!

Share
Published by
Dinesh Rajput

Recent Posts

Strategy Design Patterns using Lambda

Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…

2 years ago

Decorator Pattern using Lambda

Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…

2 years ago

Delegating pattern using lambda

Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…

2 years ago

Spring Vs Django- Know The Difference Between The Two

Technology has emerged a lot in the last decade, and now we have artificial intelligence;…

2 years ago

TOP 20 MongoDB INTERVIEW QUESTIONS 2022

Managing a database is becoming increasingly complex now due to the vast amount of data…

2 years ago

Scheduler @Scheduled Annotation Spring Boot

Overview In this article, we will explore Spring Scheduler how we could use it by…

3 years ago