loader

Ever visited a museum where a friendly tour guide takes you through the exhibits, offering fascinating insights without changing a thing about the art on display? That’s the Visitor Pattern in action! It lets you add new operations to a collection of objects without altering their classes—just like a tour guide who can comment on any exhibit without having to modify the artwork.

Why Bother with It?

  • Separation of Concerns: Just as the tour guide handles all the commentary while the exhibits remain unchanged, the Visitor Pattern separates the operations (or “what to do”) from the object structure (the exhibits).
  • Extensibility: Want to add new insights or analysis to the exhibits? You simply create a new visitor (new tour guide) without modifying the existing exhibits.
  • Clear and Organized: By keeping the operations separate, your code stays tidy. The exhibits don’t get cluttered with extra methods—they simply “accept” a visitor to perform actions on them.

How It Works (In Plain English)

  1. The Exhibits (Elements): These are your objects—in our analogy, the artworks in the museum.
  2. The Tour Guide (Visitor): The visitor is like the tour guide who walks through the museum, examining each exhibit and offering unique commentary.
  3. Accepting a Visitor: Each exhibit provides an “Accept” method that lets the tour guide come in and perform its magic. The guide then “visits” each exhibit, executing operations that vary by exhibit type.

C# Code Example

C#
using System;
using System.Collections.Generic;

// Visitor Interface: Defines visit methods for each type of exhibit.
public interface IExhibitVisitor
{
    void VisitPainting(Painting painting);
    void VisitSculpture(Sculpture sculpture);
}

// Concrete Visitor: Our friendly tour guide.
public class TourGuide : IExhibitVisitor
{
    public void VisitPainting(Painting painting)
    {
        Console.WriteLine($"TourGuide: This painting, '{painting.Title}', is a masterpiece of {painting.ArtStyle} art!");
    }
    
    public void VisitSculpture(Sculpture sculpture)
    {
        Console.WriteLine($"TourGuide: Behold, the sculpture '{sculpture.Title}'—a stunning example of {sculpture.Material} craftsmanship!");
    }
}

// Element Interface: Each exhibit can accept a visitor.
public interface IExhibit
{
    void Accept(IExhibitVisitor visitor);
}

// Concrete Element: A painting exhibit.
public class Painting : IExhibit
{
    public string Title { get; private set; }
    public string ArtStyle { get; private set; }
    
    public Painting(string title, string artStyle)
    {
        Title = title;
        ArtStyle = artStyle;
    }
    
    public void Accept(IExhibitVisitor visitor)
    {
        visitor.VisitPainting(this);
    }
}

// Concrete Element: A sculpture exhibit.
public class Sculpture : IExhibit
{
    public string Title { get; private set; }
    public string Material { get; private set; }
    
    public Sculpture(string title, string material)
    {
        Title = title;
        Material = material;
    }
    
    public void Accept(IExhibitVisitor visitor)
    {
        visitor.VisitSculpture(this);
    }
}

// Client Code: The museum where exhibits are showcased.
public class Program
{
    public static void Main()
    {
        List<IExhibit> exhibits = new List<IExhibit>
        {
            new Painting("Starry Night", "Post-Impressionism"),
            new Sculpture("The Thinker", "Bronze")
        };
        
        IExhibitVisitor tourGuide = new TourGuide();
        
        // The tour guide visits each exhibit.
        foreach (var exhibit in exhibits)
        {
            exhibit.Accept(tourGuide);
        }
    }
}

The Takeaway

The Visitor Pattern is like having an expert museum tour guide who can add new insights to every exhibit without changing the artwork itself. By encapsulating operations in a visitor, you can add functionality to a whole object structure in a neat, decoupled way. Next time you need to perform multiple operations on a complex set of objects, consider inviting a visitor to your code’s “museum”!

Happy coding—and enjoy the art of design patterns!