Easy Tutorial
❮ Front Controller Pattern Composite Entity Pattern ❯

Visitor Pattern

In the Visitor Pattern, we use a visitor class that changes the executing algorithm of the element classes. This way, the execution algorithm of the elements can vary as and when the visitor varies. This type of design pattern falls under the behavioral pattern category. According to the pattern, the element object has to accept the visitor object so that the visitor object handles the operation on the element object.

Introduction

Intent: Mainly to separate the data structure from the data operations.

Main Problem: The coupling of stable data structures with volatile operations.

When to Use: When many different and unrelated operations need to be performed on objects in an object structure, and you want to avoid polluting these object classes with these operations, use the Visitor pattern to encapsulate these operations in classes.

How to Solve: Add an interface in the visited class to provide an access point for the visitor.

Key Code: There is a method in the base data class that accepts a visitor, passing itself to the visitor.

Example: You visit a friend's house, you are the visitor, your friend accepts your visit, and based on your friend's description, you make a judgment. This is the Visitor pattern.

Advantages:

  1. Adheres to the Single Responsibility Principle.
  2. Excellent extensibility.
  3. Flexibility.

Disadvantages:

  1. Specific elements expose details to the visitor, violating the Law of Demeter.
  2. Changing specific elements is difficult.
  3. Violates the Dependency Inversion Principle by depending on concrete classes instead of abstractions.

Usage Scenarios:

  1. The classes corresponding to objects in the object structure rarely change, but new operations often need to be defined on this object structure.
  2. Many different and unrelated operations need to be performed on objects in an object structure, and you want to avoid polluting these object classes with these operations, nor do you want to modify these classes when adding new operations.

Notes: The visitor can unify functionality, such as for reports, UI, interceptors, and filters.

Implementation

We will create an interface ComputerPart that defines an accept operation. Keyboard, Mouse, Monitor, and Computer are concrete classes implementing the ComputerPart interface. We will define another interface ComputerPartVisitor that defines operations for the visitor classes. Computer uses a concrete visitor to perform the corresponding actions.

VisitorPatternDemo, our demonstration class, uses Computer and ComputerPartVisitor classes to demonstrate the usage of the Visitor pattern.

Step 1

Define an interface representing an element.

ComputerPart.java

public interface ComputerPart {
   public void accept(ComputerPartVisitor computerPartVisitor);
}

Step 2

Create concrete classes extending the above class.

Keyboard.java

public class Keyboard implements ComputerPart {
   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

Monitor.java

public class Monitor implements ComputerPart {
   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

Mouse.java

public class Mouse implements ComputerPart {
   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

Computer.java

public class Computer implements ComputerPart {
   ComputerPart[] parts;
   public Computer(){
      parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};      
   } 
   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      for (int i = 0; i < parts.length; i++) {
         parts[i].accept(computerPartVisitor);
      }
      computerPartVisitor.visit(this);
   }
}

Step 3

Define an interface representing a visitor.

ComputerPartVisitor.java

public interface ComputerPartVisitor {
   public void visit(Computer computer);
   public void visit(Mouse mouse);
   public void visit(Keyboard keyboard);
   public void visit(Monitor monitor);
}

Step 4

Create concrete visitor implementing the above class.

ComputerPartDisplayVisitor.java

public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
   @Override
   public void visit(Computer computer) {
      System.out.println("Displaying Computer.");
   }
   @Override
   public void visit(Mouse mouse) {
      System.out.println("Displaying Mouse.");
   }
   @Override
   public void visit(Keyboard keyboard) {
      System.out.println("Displaying Keyboard.");
   }
   @Override
   public void visit(Monitor monitor) {
      System.out.println("Displaying Monitor.");
   }
}

Step 5

Use ComputerPartDisplayVisitor to display the parts of Computer.

VisitorPatternDemo.java

public class VisitorPatternDemo {
   public static void main(String[] args) {
      ComputerPart computer = new Computer();
      computer.accept(new ComputerPartDisplayVisitor());
   }
}

Step 6

Execute the program, output result:

Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.
❮ Front Controller Pattern Composite Entity Pattern ❯