Definition

Visitor Pattern is a behavioral design pattern that lets you add new operations to existing object structures without modifying their classes. It separates the operation from the objects on which it operates.


Real World Analogy

Imagine a company stores different types of documents such as PDF files, Word documents, and Excel spreadsheets.

Now suppose the company wants to perform various operations on these documents:

  • Export document information
  • Scan documents for viruses
  • Generate reports
  • Calculate storage usage

One approach would be to add all these operations directly into every document class. However, as new operations are introduced, every document class would need to be modified repeatedly.

A better approach is to keep the document classes focused on representing documents and move the operations into separate visitor classes.

For example:

  • A Virus Scanner Visitor scans every document.
  • A Metadata Export Visitor extracts information from every document.
  • A Storage Report Visitor calculates storage usage.

The document classes remain unchanged while new operations can be added easily by creating new visitors. This is exactly what the Visitor Pattern does.


Design

The following UML class diagram shows the structure of the Visitor Pattern:

classDiagram

class Visitor {
    <<interface>>
    +visit(PDFDocument)
    +visit(WordDocument)
}

class Document {
    <<interface>>
    +accept(Visitor)
}

class PDFDocument {
    +accept(Visitor)
}

class WordDocument {
    +accept(Visitor)
}

class DocumentVisitor {
    +visit(PDFDocument)
    +visit(WordDocument)
}

Document <|.. PDFDocument
Document <|.. WordDocument

Visitor <|.. DocumentVisitor

PDFDocument ..> Visitor : accept()
WordDocument ..> Visitor : accept()

In this design:

  • Document defines the contract for accepting visitors.
  • PDFDocument and WordDocument are concrete elements.
  • Visitor defines operations for each document type.
  • DocumentVisitor implements the actual operation.
  • The client passes a visitor to each document.

Implementation in Java

Visitor.java
interface Visitor {
    void visit(PDFDocument pdf);
    void visit(WordDocument word);
}

The visitor interface declares a visit method for each document type that can be visited.

Document.java
interface Document {
    void accept(Visitor visitor);
}

Every document must provide an accept() method. The accept method allows a visitor to perform an operation on the document.

PDFDocument.java
class PDFDocument implements Document {
 
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
WordDocument.java
class WordDocument implements Document {
 
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

These classes represent different document types. When a visitor arrives, the document forwards itself to the appropriate visitor method. This mechanism is called Double Dispatch and is one of the key concepts behind the Visitor Pattern.

DocumentInfoVisitor.java
class DocumentInfoVisitor implements Visitor {
 
    @Override
    public void visit(PDFDocument pdf) {
        System.out.println("Processing PDF Document");
    }
 
    @Override
    public void visit(WordDocument word) {
        System.out.println("Processing Word Document");
    }
}

This visitor performs a specific operation on each document type. Notice that the document classes themselves are not modified. All operation logic is placed inside the visitor.

VisitorPattern.java
public class VisitorPattern {
 
    public static void main(String[] args) {
 
        Document pdf = new PDFDocument();
        Document word = new WordDocument();
 
        Visitor visitor = new DocumentInfoVisitor();
 
        pdf.accept(visitor);
        word.accept(visitor);
    }
}

The client creates the documents and the visitor. Each document accepts the visitor and allows it to perform the required operation. Output:

Processing PDF Document
Processing Word Document

The output shows that the same visitor can perform operations on different document types.


Real World Examples

  1. Java Compiler API
    The Java compiler uses visitors to traverse and process Abstract Syntax Trees (AST).
  2. XML and HTML Parsers
    Visitors are commonly used to traverse XML or HTML document structures and perform different operations.
  3. Document Processing Systems
    PDF, Word, and Excel documents can be processed by different visitors such as exporters, virus scanners, or report generators.