Click here to Skip to main content
Click here to Skip to main content
Go to top

Visitor Design Pattern

, 4 May 2011
Rate this:
Please Sign up or sign in to vote.
Visitor Design Pattern clearly explained with an example.

You can see this and other great articles on Design Patterns here.

The Visitor Design Pattern allows you to decouple the logics and the data structures and while applying the logics to the data structures. With this pattern, you can build classes that focus only on the data structures without knowing the logics that will be applied to the structure. At the same time, you can build classes that concentrate solely on the logics that will be applied to the structure without knowing what the structure looks like. The benefit is that the evolution of the logics and the structures can vary independently.

Let’s look at the UML of the Visitor pattern first, then we will look at an example to see how it works. Below is the UML of the Visitor Design Pattern:

  • The left hand side are the classes for the structures
    • The IElement interface defines the elements in the structure.
      • It has the Accept method that takes in an IVisitor.
    • The ConcreteElement class implements the IElement interface. You will have multiple types of ConcreteElement classes where each represents a different structure.
      • It has the Accept method that takes in an IVisitor that will apply the logic to the element.
  • The right hand side are the classes for the logics
    • The IVisitor interface defines the logics supported.
      • It has the Visit method that takes in an IElement.
    • The ConcreteVisitor class implements the IVisitor interface. You will have multiple types of ConcreteVisitor classes where each represents different logic.
      • It has the Visit method that takes in an IElement that will apply the logic to the element.

Let's see an example. We will define two types of visitors: SantaClaus and MailCarrier. They both contain logics that will be applied to the structure. 

We will define two types of structures, Household and BusinessEntity. They are the data structures where the visitors can apply their logics to. Both the Household and BusinessEntity can be visited by SantaClaus or MailCarrier.

The UML of our example is shown below:

  • The left hand side are the classes for the structures
    • The IElement interface defines the elements in the structure.
      • It has the Accept method that takes in an IVisitor.
    • The HouseHold and BusinessEntity classes implement the IElement interface.
      • They have the Accept method that takes in an IVisitor that will apply the logic to the element.
  • The right hand side are the classes for the logics
    • The IVisitor interface defines the logics supported.
      • It has the Visit method that takes in an IElement.
    • The SantaClaus and MailCarrier classes implement the IVisitor interface.
      • They have the Visit method that takes in an IElement that will apply the logic to the element.

You can extend the Visitor pattern by applying the Composite pattern to the structure part of the Visitor pattern, essentially forming a tree using the IElement as the interface for the tree structure where all the visitors can apply their logic to the tree structure. But for the purpose of demonstrating the Visitor pattern only, we will not make this extension in our implementation code.

 

Below are the implementation code and the output of our example. Notice that you can develop the structure and the logic parts independently, and yet you can easily apply the logics to the structures in the client code:

class Program
{
    static void Main(string[] args)
    {
        //first set up the structure
        List<ielement> list = new List<ielement>();
        list.Add(new Household("The Adams Family"));
        list.Add(new Household("The Jones Family"));
        list.Add(new BusinessEntity("The Oatmeal Bakery"));
        list.Add(new BusinessEntity("The Ice Cream Shop"));

        //use one visitor, or logic
        IVisitor visitor = new SantaClaus();
        foreach (IElement i in list)
            i.Accept(visitor);   //apply the logic to the element

        //use another visitor, or logic
        visitor = new MailCarrier();
        foreach (IElement i in list)
            i.Accept(visitor);  //apply the logic to the element
    }
}

public interface IElement
{
    string Name { get; set; }
    void Accept(IVisitor v);
}

public class Household : IElement
{
    private string name;

    string IElement.Name
    {
        get { return name; }
        set { name = value; }
    }

    public Household(string name)
    {
        this.name = name;
    }

    void IElement.Accept(IVisitor v)
    {
        v.Visit(this);
    }
}

public class BusinessEntity : IElement
{
    private string name;

    string IElement.Name
    {
        get { return name; }
        set { name = value; }
    }

    public BusinessEntity(string name)
    {
        this.name = name;
    }

    void IElement.Accept(IVisitor v)
    {
        v.Visit(this);
    }
}

public interface IVisitor
{
    void Visit(IElement e);
}

public class SantaClaus : IVisitor
{
    void IVisitor.Visit(IElement v)
    {
        Console.WriteLine("Santa visited " + v.Name);
    }
}

public class MailCarrier : IVisitor
{
    void IVisitor.Visit(IElement v)
    {
        Console.WriteLine("MailCarrier visited " + v.Name);
    }
}

Liked this article? You can see this and other great articles on Design Patterns here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

DevLake

United States United States
No Biography provided

Comments and Discussions

 
General5 from me Pinmembersobo12311-Nov-13 12:27 
GeneralMy vote of 2 PinmemberCrawfis9-May-11 10:54 
GeneralRe: My vote of 2 Pinmembersobo12311-Nov-13 12:30 
GeneralRe: My vote of 2 PinmemberJeremy Stafford 125-Apr-14 7:20 
GeneralMy vote of 4 Pinmemberdmjm-h3-May-11 6:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140921.1 | Last Updated 4 May 2011
Article Copyright 2011 by DevLake
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid