Visitor Design Pattern Java
There are 23 types of design pattern in Java that provides the well-defined solutions to the commonly occurring problem in application design. It represents the detailed description of the application and its flow. It is a solution to a problem that can be used in many different situations. It boosts-up the development process by providing a tested proven development paradigm. In this section, we will focus only on visitor design patterns in Java.
Visitor Pattern
It is a type of behavioral design pattern. It manages algorithms, relationships, and responsibilities between objects. It is used to perform an operation on a group of similar kinds of Objects at runtime. It decouples the operations from an object structure. Using visitor patterns, we can easily add new behaviors to the existing class hierarchy without changing the existing code. Sometimes, it is also known as a behavioral pattern.
These design patterns provide all about class object communication. These are the patterns that are specifically concerned with communication between objects.
Therefore, the primary goal of the visitor pattern is to moves the operational logic from the objects to another class. Using visitor patterns, we can achieve the open-close principle. According to the GoF, the visitor design pattern is defined as:
Representing an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
The following figure describes the concept of visitor design patterns.
The visitor pattern actually creates an external class that uses data in other classes. We can use the pattern when we need to perform operations across a dispate set of objects. It provides additional functionality to the class without modifying it.
There are the two most important methods that are used in visitor patterns. The accept() method accepts a visitor. It is provided by the Visitable class. The visit() method is called every time when we visit an element. It is implemented by the Visitor class.
Example of Visitor Design Pattern
The most common example of visitor pattern is shopping in the supermarket. In the supermarket, we pick the goods and add them to our cart. When we collect all the necessary goods to the cart, we go to the bill desk for billing. The cashier checks all the goods picked by us and tells us the total amount; we have to pay. Here, the cashier acts as a visitor.
Where and when to use it?
We should use a visitor design pattern if the application holds the following conditions:
- If we have a well-defined set of classes that are to be visited.
- Operations on said classes are not well-defined or known in advance. For example, if someone is consuming your API and you want to give consumers a way to add new ad-hoc functionality to objects. They’re also a convenient way to extend sealed classes with ad-hoc functionality.
- You perform operations of a class of objects and want to avoid run-time type testing. This is usually the case when you traverse a hierarchy of disparate objects having different properties.
Design Components
There are five major components of visitor pattern:
- Client: It is a class that acts as a consumer of the classes of the design pattern. It has the authority to access the data structure objects. It also instructs them to accept a Visitor that performs the appropriate processing.
- Visitor: It may be an interface or an abstract class. The interface contains the visit operation for all types of visitable classes.
- ConcreteVisitor: All the visit methods that are declared in abstract visitor must be implemented in the ConcreteVisitor class. Each visitor is responsible for different operations.
- Visitable: It is also an interface in which we declare the accepted operation. It is an entry point that enables an object to be visited by the visitor object.
- ConcreteVisitable: It is a class that implements the Visitable interface or class in which accept operation is defined. The object of the visitor class is passed through the object of using the accept operation.
Advantages
- We can easily add items to the system. The changes are required only in the Visitor interface. Other existing code will not be affected.
- If the logic of operation changes, then we need to make changes only in the visitor implementation.
- It reduces the maintenance cost.
- Being relatively clean, easy-to-read code.
- Type-safety, type errors are caught at compile time.
- It provides high extensibility.
Disadvantages
- It is difficult to extend if there are several implementations of the visitor interface.
- While designing the pattern, emphasis on the return type of the visit() method. Else, we will have to change the interface and all its implementations.
Implementation of Visitor Design Pattern in Java
Let’s design a pattern for the vehicles gone under service and visited by the inspector who calculates the service charge for each vehicle and total service charges including all the vehicles.
In the following example, first, we will create two interfaces named Vehicle and VehicleInspector.
Vehicle.java
VehicleInspector.java
Here, we will create five Java classes named Car.java, Van.java, Moterbike.java, VehicleInspection.java, and VehicleService.java. The classes Car, Van, and Motorbike implements the Vehicle interface. These are the vehicles going under maintenance.
Car.java
Motherbike.java
Van.java
VehicleInspection.java
VehicleService.java
When you create all the interfaces and Java classes, the project directory will look something like the following:
Output:
Service Charge for Car: 100 Service Charge for Van: 500 Service Charge for Motorbike: 50 Total Service Charge: 650
Therefore, the purpose of using visitor patterns is to give all implemented elementary functionalities. It can be used if we required to add infinite numbers of sophisticated functionalities.