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.
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.
also read:
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.
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.
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.
/** * */ package com.doj.patterns.behavior.visitor; /** * @author Dinesh.Rajput * */ public interface Element { void accept(IVisitor visitor); }
/** * */ 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; } }
/** * */ package com.doj.patterns.behavior.visitor; /** * @author Dinesh.Rajput * */ public class Director extends Employee { public Director() { super("Anamika", 45000.0, 20); } }
/** * */ package com.doj.patterns.behavior.visitor; /** * @author Dinesh.Rajput * */ public class President extends Employee { public President() { super("Arnav", 65000.0, 25); } }
/** * */ package com.doj.patterns.behavior.visitor; /** * @author Dinesh.Rajput * */ public class Clerk extends Employee { public Clerk() { super("Dinesh", 35000.0, 18); } }
/** * */ 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(); } }
/** * */ package com.doj.patterns.behavior.visitor; /** * @author Dinesh.Rajput * */ public interface IVisitor { void visit(Element element); }
/** * */ 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()); } }
/** * */ 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()); } }
/** * */ 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()); } }
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
Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…
Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…
Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…
Technology has emerged a lot in the last decade, and now we have artificial intelligence;…
Managing a database is becoming increasingly complex now due to the vast amount of data…
Overview In this article, we will explore Spring Scheduler how we could use it by…