Advanced

C-Sharp Design Patterns Visitor

This course is a starting point in the world of Visitor Design Pattern in C#. No prior experience with design patterns is required to get started.

Level: Intermediate


Table of Contents

  1. Course Overview
  2. Visitor Pattern Implementation
  1. Project Structure — Code Files
  1. UML Diagram of Visitor Pattern
  2. Summary and key points

1. Course Overview

Module 1 — Course Overview (1m 57s)

Welcome to the C# Design Patterns: Visitor training. This course is a starting point in the world of Visitor Design Pattern in C#. No prior experience with design patterns is required to get started.

Prerequisites

  • Knowledge of C# language
  • Familiarity with Visual Studio (Mac or Windows)
  • If a beginner, the C# Fundamentals course from the Pluralsight library is recommended

Topics covered

  • Define a Visitor blueprint (Visitor interface)
  • Create Concrete Visitor classes (concrete visitor classes)
  • Test the pattern in practice
  • Use an Object Structure
  • Understand real-world examples and applications of the pattern

Educational objective

At the end of this course, you will be able to identify and analyze practical use cases for the Visitor Design Pattern and integrate it into your own C# projects.


2. Implementation of the Visitor Pattern

Module 2 — Implementing the Visitor Pattern (25m 37s)

This module covers the theory and practical application of the Visitor Pattern, from blueprint definition to advanced use cases.


2.1 The Visitor Pattern explained

Pattern categorization

Design patterns are classified into three categories, as defined by the book Gang of Four (Elements of Reusable Object-Oriented Software):

CategoryDescription
CreativePatterns related to object creation
StructuralPatterns related to the structure of classes and objects
BehavioralPatterns linked to communication between objects

The Visitor Pattern belongs to the Behavioral category because it focuses on communication between objects.

Official definition

The Visitor Pattern allows you to represent an operation to be performed on the elements of an object structure. It allows you to define new operations without changing the classes of the elements it operates on.

In other words: The Visitor Pattern allows you to add behaviors to existing class hierarchies without modifying the underlying classes.

Key Features

  1. Behaviors specific to each class: the behavior can be different for each class when a single visitor is used.
  2. Miscellaneous hierarchy: The existing class hierarchy can be diverse and not connected by inheritance, as long as each class is marked as visitable.
  3. Separation of concerns: Operation logic is extracted from element classes and grouped into visitors.

Pattern components (conceptual UML diagram)

The pattern has several essential components:

+------------------+          +--------------------+
|   «interface»    |          |    «interface»     |
|    IVisitor      |          |  IVisitableElement |
+------------------+          +--------------------+
| + VisitBook()    |          | + Accept(IVisitor) |
| + VisitVinyl()   |          +--------------------+
| + Print()        |                    △
+------------------+                    |
         △                    +---------+---------+
         |                    |                   |
+--------+--------+    +------+-------+   +-------+------+
| DiscountVisitor |    |     Book     |   |    Vinyl     |
+-----------------+    +--------------+   +--------------+
| + VisitBook()   |    | + Accept()   |   | + Accept()   |
| + VisitVinyl()  |    +--------------+   +--------------+
| + Print()       |
| + Reset()       |
+-----------------+
+--------+--------+
| SalesVisitor    |
+-----------------+
| + VisitBook()   |
| + VisitVinyl()  |
| + Print()       |
+-----------------+

Component details:

  • IVisitor (interface): contains a Visit method for each class in the project. The concrete classes implementing this interface provide the desired behavior.
  • IVisitableElement (interface): contains a single Accept method, which takes a visitor as a parameter.
  • Concrete Elements (Book, Vinyl): implement IVisitableElement. The Accept method delegates the call to the visitor by passing this as an argument.
  • Concrete Visitors (DiscountVisitor, SalesVisitor): implement IVisitor with logic specific to each item type.
  • Object Structure (ObjectStructure): manages the collection of visitable elements and orchestrates the application of visitors.

Pattern execution flow

Client
  │
  │ ApplyVisitor(discountVisitor)
  ▼
ObjectStructure
  │
  │ foreach item → item.Accept(visitor)
  ▼
Book.Accept(visitor)       Vinyl.Accept(visitor)
  │                              │
  │ visitor.VisitBook(this)      │ visitor.VisitVinyl(this)
  ▼                              ▼
DiscountVisitor.VisitBook() DiscountVisitor.VisitVinyl()

2.2 Creation of the Visitor blueprint

Presentation of the initial project

The starter project (M02_Starter) contains a simple class structure for a Barnes & Noble-style retail store:

  • Item.cs: base class with properties ID, Price, and method GetDiscount
  • Book and Vinyl: subclasses inheriting from Item
  • Program.cs: entry point with an array of predefined items

The goal is to use the Visitor Pattern to calculate item discounts and number of items sold without adding logic to existing classes.

Creation of fundamental interfaces

The first step is to create a new Visitor.cs file containing the two fundamental interfaces of the pattern:

IVisitor — the interface that all concrete visitors must implement:

public interface IVisitor
{
    void VisitBook(Book book);
    void VisitVinyl(Vinyl vinyl);
    void Print();
}

IVisitableElement — the interface that all visitable elements must implement:

public interface IVisitableElement
{
    void Accept(IVisitor visitor);
}

Important note: These two interfaces can also be abstract classes if you are more comfortable with that approach. The course uses interfaces for clarity and flexibility.

Make classes visitable

The Book and Vinyl classes must implement IVisitableElement by adding the Accept method. It is this method which establishes the link between the element and the visitor:

public class Book : Item, IVisitableElement
{
    public Book(int id, double price) : base(id, price) { }

    public void Accept(IVisitor visitor)
    {
        visitor.VisitBook(this);   // délègue au visitor en passant "this"
    }
}

public class Vinyl : Item, IVisitableElement
{
    public Vinyl(int id, double price) : base(id, price) { }

    public void Accept(IVisitor visitor)
    {
        visitor.VisitVinyl(this);  // délègue au visitor en passant "this"
    }
}

Key concept — Double Dispatch: The Visitor Pattern exploits the principle of double dispatch. When item.Accept(visitor) is called, the actual type of item determines which Accept method is executed, which in turn calls the correct method on the visitor. It is this mechanism that allows dynamic dispatching to the correct logic.


2.3 Implementing a Concrete Visitor

The DiscountVisitor — Discount calculation

The first functionality to add is the calculation and display of discounts depending on the item type. The discount logic is:

  • Books: 10% discount if the price is less than $20, otherwise full price
  • Vinyl: 15% discount systematically
public class DiscountVisitor : IVisitor
{
    private double _savings;

    public void VisitBook(Book book)
    {
        var discount = 0.0;

        if (book.Price < 20.00)
        {
            discount = book.GetDiscount(0.10);
            Console.WriteLine($"DISCOUNTED: Book #{book.ID} is now ${Math.Round(book.Price - discount, 2)}");
        }
        else
        {
            Console.WriteLine($"FULL PRICE: Book #{book.ID} is ${book.Price}");
        }

        _savings += discount;
    }

    public void VisitVinyl(Vinyl vinyl)
    {
        var discount = vinyl.GetDiscount(0.15);
        Console.WriteLine($"SUPER SAVINGS: Vinyl #{vinyl.ID} is now ${Math.Round(vinyl.Price - discount, 2)}");

        _savings += discount;
    }

    public void Print()
    {
        Console.WriteLine($"\nYou saved a total of ${Math.Round(_savings, 2)} on today's order!");
    }

    public void Reset()
    {
        _savings = 0.0;
    }
}

Important points about this visitor:

  • The private field _savings accumulates state across all visits — this is an important feature of concrete visitors.
  • The Reset() method allows you to reset the state of the visitor for new use.
  • Each Visit method receives the typed concrete object (not an interface), which gives access to all specific properties.
  • Using Math.Round on 2 decimal places avoids uncontrolled decimal numbers in the display.

The SalesVisitor — Sales counting

Once the structure is in place, adding a second visitor is very simple. The SalesVisitor counts the number of items sold by type:

public class SalesVisitor : IVisitor
{
    private int BookCount = 0;
    private int VinylCount = 0;

    public void VisitBook(Book book)
    {
        BookCount++;
    }

    public void VisitVinyl(Vinyl vinyl)
    {
        VinylCount++;
    }

    public void Print()
    {
        Console.WriteLine($"Books sold: {BookCount} \nVinyl sold: {VinylCount}");
        Console.WriteLine($"The store sold {BookCount + VinylCount} units today!");
    }
}

Key observation: The ease of adding the SalesVisitor perfectly illustrates one of the great advantages of the Visitor Pattern — we can add new functionalities without touching existing classes (Book, Vinyl, Item).


2.4 Testing the Visitor Pattern

Initial test program (without ObjectStructure)

Firstly, we can test directly from Program.cs by manually iterating over the list of items:

List<IVisitableElement> items = new List<IVisitableElement>
{
    new Book(12345, 11.99),
    new Book(78910, 22.79),
    new Vinyl(11198, 17.99),
    new Book(63254, 9.79)
};

var discountVisitor = new DiscountVisitor();

foreach (var item in items)
{
    item.Accept(discountVisitor);
}

discountVisitor.Print();

Expected console result:

DISCOUNTED: Book #12345 is now $10.79
FULL PRICE: Book #78910 is $22.79
SUPER SAVINGS: Vinyl #11198 is now $15.29
DISCOUNTED: Book #63254 is now $8.81

You saved a total of $3.88 on today's order!

Analysis of results:

  • Book #12345 (11.99$) → price < 20$ → discount 10% → final price 10.79$
  • Book #78910 (22.79$) → price ≥ 20$ → full price 22.79$
  • Vinyl #11198 (17.99$) → systematic 15% discount → final price 15.29$
  • Book #63254 (9.79$) → price < 20$ → discount 10% → final price 8.81$

Note: Notice the important change in the list declaration: we go from List<Object> (in the Starter) to List<IVisitableElement> (in the Final). This is necessary to be able to call item.Accept(visitor) polymorphically.


2.5 Adding an Object Structure

Role and usefulness of the Object Structure

The Object Structure is the main control panel of the Visitor Pattern. It allows you to:

  • Store an iterable collection of visitable items
  • Edit this collection (adding, removing items)
  • Iterate over elements and call Accept centrally

Although not always present in every implementation of the pattern, its use is strongly recommended as an additional level of abstraction.

Implementing the ObjectStructure

public class ObjectStructure
{
    private List<IVisitableElement> _cart;

    public ObjectStructure(List<IVisitableElement> items)
    {
        _cart = items;
    }

    public void RemoveItem(IVisitableElement item)
    {
        _cart.Remove(item);
    }

    public void ApplyVisitor(IVisitor visitor)
    {
        Console.WriteLine("\n------- Visitor Breakdown -------");
        foreach (var item in _cart)
            item.Accept(visitor);

        visitor.Print();
    }
}

Details of responsibilities:

MethodResponsibility
ObjectStructure(List<IVisitableElement>)Constructor: initializes the internal list with the elements provided
RemoveItem(IVisitableElement)Wraps the removal of an item from the private list
ApplyVisitor(IVisitor)Iterates over all elements and calls Accept on each, then calls Print

Why encapsulate the list?

The _cart list is private to prevent accidental modifications from the outside. The RemoveItem (and potentially AddItem) methods expose controlled access to this list.

Complete program with ObjectStructure

class Program
{
    static void Main(string[] args)
    {
        List<IVisitableElement> items = new List<IVisitableElement>
        {
            new Book(12345, 11.99),
            new Book(78910, 22.79),
            new Vinyl(11198, 17.99),
            new Book(63254, 9.79)
        };

        var cart = new ObjectStructure(items);

        var discountVisitor = new DiscountVisitor();
        var salesVisitor = new SalesVisitor();

        // Premier passage : calcul des rabais
        cart.ApplyVisitor(discountVisitor);

        // Second passage : comptage des ventes
        cart.ApplyVisitor(salesVisitor);

        // Réinitialisation du visitor et suppression d'un item
        discountVisitor.Reset();
        cart.RemoveItem(items[2]);  // on retire le Vinyl

        // Troisième passage : recalcul des rabais sans le Vinyl
        cart.ApplyVisitor(discountVisitor);
    }
}

Expected console result:

------- Visitor Breakdown -------
DISCOUNTED: Book #12345 is now $10.79
FULL PRICE: Book #78910 is $22.79
SUPER SAVINGS: Vinyl #11198 is now $15.29
DISCOUNTED: Book #63254 is now $8.81

You saved a total of $3.88 on today's order!

------- Visitor Breakdown -------
Books sold: 3
Vinyl sold: 1
The store sold 4 units today!

------- Visitor Breakdown -------
DISCOUNTED: Book #12345 is now $10.79
FULL PRICE: Book #78910 is $22.79
DISCOUNTED: Book #63254 is now $8.81

You saved a total of $1.18 on today's order!

Analysis of the third pass:

  • After discountVisitor.Reset(), the _savings counter is reset to 0
  • After cart.RemoveItem(items[2]), the Vinyl is removed from the cart
  • The third ApplyVisitor therefore only processes the remaining 3 books
  • Total savings go from $3.88 to $1.18 (without the $2.70 Vinyl rebate)

2.6 Use cases and applications

When to use the Visitor Pattern?

The Visitor Pattern is particularly suitable in the following situations:

  1. Class variety: When a project contains a variety of classes, potentially with different interfaces and inheritance structures, that require behavior specific to each class.

  2. Unrelated behaviors: when different, unrelated behaviors need to be applied without polluting existing classes.

  3. Stable hierarchy: when the existing class structure is unlikely to change, but new behaviors should be able to be added at will.

  4. State accumulation: when it is necessary to collect related behaviors and accumulate state across different classes in a complex hierarchy.

Advantages of the pattern

AdvantageExplanation
ExtensibilityAdd new behaviors without modifying existing classes
Separation of ConcernsThe operations logic is grouped in visitors
Specific behavior per classEach class can have a different behavior with the same visitor
State accumulationVisitors can maintain a state across multiple visits
Compatibility with other patternsWorks well with Composite Pattern and Interpreter Pattern

Disadvantages and limitations

DisadvantageExplanation
Cost of modifying the hierarchyEach change in the class hierarchy requires an update of IVisitor and of all concrete visitors
Potential encapsulation breakThe pattern often needs access to the internal state of elements to work
Coupling with concrete typesThe IVisitor interface is coupled to concrete types (one Visit method per type)

General rule: If your class hierarchy changes often, the Visitor Pattern can cause a lot of maintenance. In this case, other approaches might be more suitable.

Relations with other patterns

  • Composite Pattern: the Visitor Pattern can work with a class structure already using the Composite Pattern, making it easier to traverse object trees.
  • Interpreter Pattern: The Visitor Pattern can be used to perform interpretation as part of the Interpreter Pattern.

3. Project Structure — Code Files

3.1 Starter project

The starting project (M02_Starter) contains only the base class hierarchy, without any implementation of the Visitor Pattern.

Item.cs — Base classes

using System;
using System.Collections.Generic;
using System.Text;

namespace Visitor_Pattern
{
    public class Item
    {
        public int ID;
        public double Price;

        public Item(int id, double price)
        {
            this.ID = id;
            this.Price = price;
        }

        public double GetDiscount(double percentage)
        {
            return Math.Round(Price * percentage, 2);
        }
    }

    public class Book : Item
    {
        public Book(int id, double price) : base(id, price) { }
    }

    public class Vinyl : Item
    {
        public Vinyl(int id, double price) : base(id, price) { }
    }
}

Observations:

  • Item is the base class with two public properties: ID (int) and Price (double)
  • The GetDiscount(double percentage) method calculates the discount amount from a percentage and returns the result rounded to 2 decimal places
  • Book and Vinyl inherit from Item and just pass parameters to parent constructor via base(id, price)

Program.cs — Initial entry point

using System;
using System.Collections.Generic;

namespace Visitor_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Object> items = new List<Object>
            {
                new Book(12345, 11.99),
                new Book(78910, 22.79),
                new Vinyl(11198, 17.99),
                new Book(63254, 9.79)
            };
        }
    }
}

Note: The list is of type List<Object> in the Starter. It will be changed to List<IVisitableElement> during the implementation of the pattern.


3.2 Final Draft (Final)

The final project (M02_Final) contains the complete implementation of the Visitor Pattern with all files.

Item.cs — Classes made visitable

using System;
using System.Collections.Generic;
using System.Text;

namespace Visitor_Pattern
{
    public class Item
    {
        public int ID;
        public double Price;

        public Item(int id, double price)
        {
            this.ID = id;
            this.Price = price;
        }

        public double GetDiscount(double percentage)
        {
            return Math.Round(Price * percentage, 2);
        }
    }

    public class Book : Item, IVisitableElement
    {
        public Book(int id, double price) : base(id, price) { }

        public void Accept(IVisitor visitor)
        {
            visitor.VisitBook(this);
        }
    }

    public class Vinyl : Item, IVisitableElement
    {
        public Vinyl(int id, double price) : base(id, price) { }

        public void Accept(IVisitor visitor)
        {
            visitor.VisitVinyl(this);
        }
    }
}

Changes compared to Starter:

  • Book now implements IVisitableElement with the Accept method which calls visitor.VisitBook(this)
  • Vinyl now implements IVisitableElement with the Accept method which calls visitor.VisitVinyl(this)
  • The Item class itself is not modified — this is a fundamental principle of the Visitor Pattern

Visitor.cs — Concrete interfaces and visitors

using System;
using System.Collections.Generic;
using System.Text;

namespace Visitor_Pattern
{
    // Interface fondamentale 1 : le Visitor
    public interface IVisitor
    {
        void VisitBook(Book book);
        void VisitVinyl(Vinyl vinyl);
        void Print();
    }

    // Interface fondamentale 2 : l'Element visitable
    public interface IVisitableElement
    {
        void Accept(IVisitor visitor);
    }

    // Concrete Visitor 1 : calcul des rabais
    public class DiscountVisitor : IVisitor
    {
        private double _savings;

        public void VisitBook(Book book)
        {
            var discount = 0.0;

            if (book.Price < 20.00)
            {
                discount = book.GetDiscount(0.10);
                Console.WriteLine($"DISCOUNTED: Book #{book.ID} is now ${Math.Round(book.Price - discount, 2)}");
            }
            else
            {
                Console.WriteLine($"FULL PRICE: Book #{book.ID} is ${book.Price}");
            }

            _savings += discount;
        }

        public void VisitVinyl(Vinyl vinyl)
        {
            var discount = vinyl.GetDiscount(0.15);
            Console.WriteLine($"SUPER SAVINGS: Vinyl #{vinyl.ID} is now ${Math.Round(vinyl.Price - discount, 2)}");

            _savings += discount;
        }

        public void Print()
        {
            Console.WriteLine($"\nYou saved a total of ${Math.Round(_savings, 2)} on today's order!");
        }

        public void Reset()
        {
            _savings = 0.0;
        }
    }

    // Concrete Visitor 2 : comptage des ventes
    public class SalesVisitor : IVisitor
    {
        private int BookCount = 0;
        private int VinylCount = 0;

        public void VisitBook(Book book)
        {
            BookCount++;
        }

        public void VisitVinyl(Vinyl vinyl)
        {
            VinylCount++;
        }

        public void Print()
        {
            Console.WriteLine($"Books sold: {BookCount} \nVinyl sold: {VinylCount}");
            Console.WriteLine($"The store sold {BookCount + VinylCount} units today!");
        }
    }
}

ObjectStructure.cs — Object structure

using System;
using System.Collections.Generic;
using System.Text;

namespace Visitor_Pattern
{
    public class ObjectStructure
    {
        private List<IVisitableElement> _cart;

        public ObjectStructure(List<IVisitableElement> items)
        {
            _cart = items;
        }

        public void RemoveItem(IVisitableElement item)
        {
            _cart.Remove(item);
        }

        public void ApplyVisitor(IVisitor visitor)
        {
            Console.WriteLine("\n------- Visitor Breakdown -------");
            foreach (var item in _cart)
                item.Accept(visitor);

            visitor.Print();
        }
    }
}

Program.cs — Final entry point

using System;
using System.Collections.Generic;

namespace Visitor_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {
            List<IVisitableElement> items = new List<IVisitableElement>
            {
                new Book(12345, 11.99),
                new Book(78910, 22.79),
                new Vinyl(11198, 17.99),
                new Book(63254, 9.79)
            };

            var cart = new ObjectStructure(items);

            var discountVisitor = new DiscountVisitor();
            var salesVisitor = new SalesVisitor();

            cart.ApplyVisitor(discountVisitor);
            cart.ApplyVisitor(salesVisitor);

            discountVisitor.Reset();
            cart.RemoveItem(items[2]);
            cart.ApplyVisitor(discountVisitor);
        }
    }
}

4. Visitor Pattern UML Diagram

Here is the complete representation of the Visitor Pattern architecture as implemented in this course:

                    ┌─────────────────────────────────────────────────┐
                    │            «interface» IVisitor                  │
                    ├─────────────────────────────────────────────────┤
                    │ + VisitBook(book: Book): void                   │
                    │ + VisitVinyl(vinyl: Vinyl): void                │
                    │ + Print(): void                                  │
                    └───────────────────┬─────────────────────────────┘
                                        │ implements
              ┌─────────────────────────┴──────────────────────────┐
              │                                                     │
┌─────────────┴────────────────┐             ┌────────────────────┴──────────┐
│      DiscountVisitor         │             │        SalesVisitor            │
├──────────────────────────────┤             ├───────────────────────────────┤
│ - _savings: double           │             │ - BookCount: int               │
├──────────────────────────────┤             │ - VinylCount: int              │
│ + VisitBook(book): void      │             ├───────────────────────────────┤
│ + VisitVinyl(vinyl): void    │             │ + VisitBook(book): void        │
│ + Print(): void              │             │ + VisitVinyl(vinyl): void      │
│ + Reset(): void              │             │ + Print(): void                │
└──────────────────────────────┘             └───────────────────────────────┘

                    ┌─────────────────────────────────────────────────┐
                    │         «interface» IVisitableElement            │
                    ├─────────────────────────────────────────────────┤
                    │ + Accept(visitor: IVisitor): void               │
                    └───────────────────┬─────────────────────────────┘
                                        │ implements
              ┌─────────────────────────┴──────────────────────────┐
              │                                                     │
┌─────────────┴──────────┐                          ┌──────────────┴──────────┐
│          Book          │                          │         Vinyl           │
├────────────────────────┤                          ├─────────────────────────┤
│ (hérite de Item)       │                          │ (hérite de Item)        │
├────────────────────────┤                          ├─────────────────────────┤
│ + Accept(visitor): void│                          │ + Accept(visitor): void │
└────────────────────────┘                          └─────────────────────────┘
              │ hérite de                                        │ hérite de
              └─────────────────────┬────────────────────────────┘
                                    │
                    ┌───────────────┴──────────────────┐
                    │              Item                 │
                    ├──────────────────────────────────┤
                    │ + ID: int                        │
                    │ + Price: double                  │
                    ├──────────────────────────────────┤
                    │ + Item(id, price)                │
                    │ + GetDiscount(pct): double       │
                    └──────────────────────────────────┘

                    ┌──────────────────────────────────────────────┐
                    │            ObjectStructure                    │
                    ├──────────────────────────────────────────────┤
                    │ - _cart: List<IVisitableElement>             │
                    ├──────────────────────────────────────────────┤
                    │ + ObjectStructure(items)                     │
                    │ + RemoveItem(item): void                     │
                    │ + ApplyVisitor(visitor): void                │
                    └──────────────────────────────────────────────┘

5. Summary and key points

What we learned

ConceptDescription
Visitor PatternBehavioral pattern for adding behaviors to class hierarchies without modifying them
IVisitorInterface defining a Visit method for each type of concrete element
IVisitableElementInterface defining the Accept method which accepts a visitor
Concrete VisitorClass implementing IVisitor with specific logic for each type
Double DispatchMechanism at the heart of the pattern: Accept delegates to Visit by passing this
Object StructureManager of the collection of visitable elements and orchestrator of visitors
State accumulationVisitors can maintain a state (_savings, BookCount) across visits

Implementation Checklist

To implement the Visitor Pattern in a C# project:

  • Create the IVisitor interface with a Visit method for each element type
  • Create the IVisitableElement interface with the Accept(IVisitor) method
  • Implement IVisitableElement in each element class
  • In each Accept method, call the corresponding Visit method on the visitor
  • Create one or more concrete visitors implementing IVisitor
  • (Optional) Create an ObjectStructure to manage the collection of elements
  • From the calling code, instantiate the visitors and call Accept or ApplyVisitor

Pattern selection criteria

Use the Visitor Pattern when:

  • You have a diverse class hierarchy that requires type-specific behaviors
  • You want to add new operations without modifying existing classes
  • Class hierarchy is stable and unlikely to change
  • You need to accumulate state or gather information across different classes

Avoid the Visitor Pattern when:

  • Class hierarchy changes frequently (high maintenance cost)
  • Strict encapsulation is critical (pattern may need to access internal states)
  • The hierarchy is simple with few types (over-engineering)

Relations with other patterns

  • Composite Pattern: the Visitor Pattern integrates naturally with the Composite Pattern to traverse tree structures
  • Interpreter Pattern: the Visitor Pattern can be used to perform interpretation in the context of the Interpreter Pattern
  • Iterator Pattern: the Object Structure can use an Iterator to traverse the elements


Search Terms

c-sharp · design · patterns · visitor · testing · architecture · c# · .net · development · pattern · classes · initial · object · objectstructure · concrete · creation · diagram · entry · interfaces · item.cs · point · program · program.cs · relations

Interested in this course?

Contact us to book it or get a custom training plan for your team.