Visitor Design Pattern in C#

Visitor Design Pattern in C# with Real-Time Example

In this article, I am going to discuss the Visitor Design Pattern in C# with examples. Please read our previous article where we discussed the Command Design Pattern in C#. The Visitor Design Pattern falls under the category of Behavioural Design Pattern i.e. it is used to change the behavior of a class. As part of this article, we are going to discuss the following pointers related to the Visitor Design Pattern in detail.

  1. What is the Visitor Design Pattern?
  2. Real-Time Example of Visitor Design Pattern.
  3. Implementing the Visitor Design Pattern in C#.
  4. When to use Visitor Design Pattern in C#?
What is the Visitor Design Pattern?

In the Visitor Design Pattern, we use a Visitor object which changes the executing algorithm of an element object. In this way, when the visitor varies, the execution algorithm of the element object can also vary. As per the Visitor Design Pattern, the element object has to accept the visitor object so that the visitor object handles the operation on the element object.

The Visitor Design Pattern should be used when you have distinct and unrelated operations to perform across a structure of objects (element objects). This avoids adding in code throughout your object structure that is better kept separate.

To understand the above explanation better, please have a look at the following diagram. On the left-hand side, you can see visitor objects and on the right-hand side, you have the object structure. The object structure can be a collection of type either Array, List, ArrayList, etc. As you can see, the object structure (collection) can have multiple elements (i.e. Element 1, Element 2, Element 3 and Element 4). Now if you want to perform some common operation on each element, then you need to use the visitor design pattern. Here, the Visitor object will visit each element of the object structure and perform the common operation.

What is the Visitor Design Pattern in C#?

Now it is possible to vary the operation as the visitor varies. For example, for Visitor 1, you may perform operation A on each element whereas, for Visitor 2, you may perform operation B on each element.

If still, this is not clear at the moment then don’t worry we will try to understand the above explanation with some real-time examples.

Real-Time Example of Visitor Design Pattern:

Please have a look at the following image. Here, we have a school and in school, lots of kids are studying. One day the school management has decided to perform a health checkup for all the kids. So, what the school management has done is they appointment one child specialist doctor. What the doctor will do is, he will visit the school and check the health of each and every kid. Once he has checked the health of each kid, then he provides the reports to the school management.

Real-Time Example of Visitor Design Pattern

So, here in this example, the doctor is nothing but a visitor and the object structure is a collection of Kids where each kid is an element object.

In the same manner, one school bag sales company want to promote their school bag. So, the company communicates with the school management and decided to give a school to each kid as a gift. So, the company salesman visits the school and give school bag to each kid. For better understanding please have a look at the following diagram.

Visitor Design Pattern Real-Time Example in C#

Here, the salesman is the visitor and the object structure is the same collection of kids where each kid is an element.

How to Implement the Visitor Design Pattern in C#?

Let us implement the above example using the Visitor Design Pattern in C# step by step.

Step1: Creating Element interface

Create an interface with the name IElement.cs and then copy and paste the following code in it. The IElement interface declares an Accept method which takes the base Visitor interface as an argument.

namespace VisitorDesignPattern
{
   public interface IElement
    {
        void Accept(IVisitor visitor);
    }
}

Note: Later we are going to declare the base interface IVisitor.

Step2: Creating Concrete Elements

Create a class file with the name Kid.cs and then copy and paste the following code in it. This Concrete Element Kid implements the Accept method defined by the IElement interface.

namespace VisitorDesignPattern
{
    public class Kid : IElement
    {
        public string KidName { get; set; }
        
        public Kid(string name)
        {
            KidName = name;
        }
        
        public void Accept(IVisitor visitor)
        {
            visitor.Visit(this);
        }
    }
}
Step3: Creating Visitor Interface

Create an interface with the name IVisitor.cs and then copy and paste the following code in it. This IVisitor interface declares a method for each Concrete Element in the object structure.

namespace VisitorDesignPattern
{
    public interface IVisitor
    {
        void Visit(IElement element);
    }
}
Step4: Creating Concrete Visitors
Concrete Visitor1:

Create a class with the name Doctor.cs and then copy and paste the following code in it. This Concrete Visitor class implements each operation declared by the IVisitor interface. Each operation implements a fragment of the algorithm needed for that object.

using System;
namespace VisitorDesignPattern
{
    public class Doctor : IVisitor
    {
        public string Name { get; set; }

        public Doctor(string name)
        {
            Name = name;
        }
        
        public void Visit(IElement element)
        {
            Kid kid = (Kid)element;
            Console.WriteLine("Doctor: " + this.Name+ " did the health checkup of the child: "+ kid.KidName);
        }
    }
}
Concrete Visitor2:

Create a class with the name Salesman.cs and then copy and paste the following code in it. This Concrete Visitor class also implements the operation defined by the IVisitor interface.

using System;
namespace VisitorDesignPattern
{
    class Salesman : IVisitor
    {
        public string Name { get; set; }

        public Salesman(string name)
        {
            Name = name;
        }

        public void Visit(IElement element)
        {
            Kid kid = (Kid)element;
            Console.WriteLine("Salesman: " + this.Name + " gave the school bag to the child: "
                            + kid.KidName);
        }
    }
}
Step5: Creating Object Structure

Create a class file with the name School.cs and then copy and paste the following code in it. The Object Structure can enumerate its elements and may provide a high-level interface to allow the Visitor to visit its elements.

using System.Collections.Generic;
namespace VisitorDesignPattern
{
    public class School
    {
        private static List<IElement> elements;
        static School()
        {
            elements = new List<IElement>
            {
                new Kid("Ram"),
                new Kid("Sara"),
                new Kid("Pam")
            };
        }

        public void PerformOperation(IVisitor visitor)
        {
            foreach (var kid in elements)
            {
                kid.Accept(visitor);
            }
        }
    }
}
Step6: Client Code

Modify the Main method as shown below.

using System;
namespace VisitorDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            School school = new School();

            var visitor1 = new Doctor("James");
            school.PerformOperation(visitor1);
            Console.WriteLine();

            var visitor2 = new Salesman("John");
            school.PerformOperation(visitor2);

            Console.Read();
        }
    }
}

Output:

How to Implement the Visitor Design Pattern in C#?

In short, here we created two visitors (visitor1 and visitor2) and they visited each and every kid in the school and perform their operations.

Participants in the Visitor Design Pattern:

The classes and objects participating in the Visitor Design Pattern are as follows:

Visitor (IVisitor): This is an interface and it declares the Visit operation for each element in the object structure (i.e. for concrete visitors).

ConcreteVisitor (Doctor, Salesman): These are the subclasses that implement each operation declared by the IVisitor interface. Each operation implements a fragment of the algorithm defined for the corresponding class or object in the structure.

Element (IElement): This is an interface that defines an Accept operation that takes a visitor as an argument.

ConcreteElement (Kid): This is a class that implements the Element (i.e. IElement) interface i.e. this class implements the Accept operation that takes a visitor as an argument.

ObjectStructure (School): This is a class that holds all the elements (i.e. a collection of kids) and provides a high-level interface that allows the visitor to visit all the elements.

When to use Visitor Design Pattern in C#?
  1. An object structure must have many unrelated operations to perform on it.
  2. An object structure cannot change but operations performed on it can change.
  3. The operations need to perform on the concrete classes of an object structure.
  4. Exposing the internal state or operations of the object structure is acceptable.
  5. Operations should be able to operate on multiple object structures that implement the same interface.

In the next article, I am going to discuss the Strategy Design Pattern in C# with real-time examples. Here, in this article, I try to explain the Visitor Design Pattern step by step with some examples. I hope you understood the need and use of the Visitor Design Pattern in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *