Visitor Design Pattern


Here, we will see how to create Visitor Design Pattern with example.

Visitor Design Pattern

The Visitor design pattern is a behavioral design pattern that allows you to add further operations to objects without modifying them. It lets you define new operations on a set of objects by separating the algorithm from the object structure. In this pattern, you define a visitor class that performs the required operations on elements of a collection.

Example

Consider a company where each employee is an object, and the company occasionally needs to apply different operations on these employees, such as calculating their bonus, reviewing performance, or conducting appraisals. Instead of embedding all these operations within the Employee class, we can use the Visitor pattern.

Here is the image illustrating the Visitor design pattern applied to a company setting. The Developer and Manager are connected to operations like 'Calculating Bonus', 'Performance Review', and 'Appraisal', showing how visitors can perform operations without altering the employee objects.

Visitor Design Pattern

Advantages of the Visitor Pattern

  1. Single Responsibility Principle (SRP) - The Visitor pattern helps keep the classes clean by moving unrelated operations out of the objects themselves into separate classes (visitors).
  2. Open/Closed Principle (OCP) - You can add new operations without changing the classes of the objects that operate on. Instead, you add new visitor classes.
  3. Flexible - The visitor can gather related operations into a single class. It’s easy to define new operations over a collection of objects.
  4. Double Dispatch - It allows a visitor class to execute different behaviors dynamically based on both the type of the object it is working on and the type of visitor itself.

When to Use the Visitor Pattern

  1. Structure of Related Classes - When you have a group of classes with varying functionality, and you want to add additional behavior to these classes without changing them.
  2. Separate Operations - When you need to perform many different operations on objects in a class hierarchy, and the operations vary across objects.
  3. Object Structure Rarely Changes - When the class structure is stable and doesn’t change often, but operations applied to these classes change frequently.
  4. Multiple Distinct Operations - When classes will be subjected to multiple different and distinct operations that may vary across instances.

Problems in a System without the Visitor Pattern

  1. Tight Coupling - Without the Visitor pattern, you would need to add methods directly to the classes themselves, making them bulky and tightly coupled with functionality.
  2. Violation of OCP - Adding new operations would require modifying the object classes themselves, violating the Open/Closed Principle.
  3. Inconsistent Behavior - Each object class may handle its behavior differently, leading to inconsistencies in the operation implementations.
  4. Difficulty in Adding Operations - Adding new operations could become cumbersome, especially if they need to interact with multiple different objects or classes in the system.

Example of the Visitor Pattern

Consider a company where each employee is an object, and the company occasionally needs to apply different operations on these employees, such as calculating their bonus, reviewing performance, or conducting appraisals. Instead of embedding all these operations within the Employee class, we can use the Visitor pattern.

// Employee hierarchy
public interface IEmployee
{
    void Accept(IVisitor visitor);
}

public class Developer : IEmployee
{
    public string Name { get; set; }
    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class Manager : IEmployee
{
    public string Name { get; set; }
    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

// Visitor interface
public interface IVisitor
{
    void Visit(Developer developer);
    void Visit(Manager manager);
}

// Concrete visitor
public class BonusVisitor : IVisitor
{
    public void Visit(Developer developer)
    {
        Console.WriteLine($"Bonus given to Developer {developer.Name}");
    }

    public void Visit(Manager manager)
    {
        Console.WriteLine($"Bonus given to Manager {manager.Name}");
    }
}

// Usage
class Program
{
    static void Main(string[] args)
    {
        List<IEmployee> employees = new List<IEmployee>
        {
            new Developer { Name = "Rohatash" },
            new Manager { Name = "Mohit" }
        };

        IVisitor bonusVisitor = new BonusVisitor();

        foreach (var employee in employees)
        {
            employee.Accept(bonusVisitor);
        }
    }
}

Output

Visitor Design Pattern

Real-World Example of the Visitor Pattern

  1. Compiler Design - In a compiler, the abstract syntax tree (AST) is a complex structure with many different node types (for expressions, statements, etc.). Different operations, such as interpreting, compiling, or type-checking, can be performed on these nodes using the Visitor pattern.

  2. Document Processing - In a document processing system, you can have different elements like paragraphs, tables, and images. The Visitor pattern allows performing various operations like rendering, exporting to different formats, or spell-checking without altering the document structure.

Applications of the Visitor Pattern

  1. Compilers and Interpreters - To separate algorithms for interpreting, compiling, or optimizing code from the structure of the language syntax.
  2. Graphics Libraries - For rendering different shapes like circles, squares, or triangles while adding functionality such as calculating area, perimeter, or bounding boxes.
  3. Object Hierarchies in Business Applications - To process complex hierarchies like customer records, invoices, or financial data and apply operations such as auditing, reporting, or calculating.
  4. UI Components - In graphical user interfaces, to separate the functionality of components like buttons, checkboxes, and menus while applying different operations like rendering, enabling/disabling, or checking status.

Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question