Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Visitor Design Pattern

4.89/5 (23 votes)
10 Sep 2009CPOL3 min read 80.5K   598  
This article shows a case study about how we use the Visitor pattern in a daycare center reward system.

Background

Again, my favorite place - Elizabeth's daycare center.

From my previous article, I talked about how to use the Strategy Pattern to develop a system for the doctor visiting. In that case, I only focused on the Doctor objects to illustrate how those dynamic actions will be impacted when the strategy object (different doctors) changes.

In this article, I am going to focus on those visitable/Kid objects which are examined by the Doctors.

On Elizabeth's daycare calendar, it shows Dr. WANG (EyeDoctor) gives eye screens on the 15th each month for all the kids, Dr. Fong (SLP - Speech Language Pathologist) gives speech evaluations on the 28th each month. And parents may visit their kids at anytime.

For each visitor's visit, all the related status needs to be updated after the Doctor's visits. EyeDoctor will update EyeStatus only, and SLP updates SpeechStatus as well. Parents will update both EyeStatus and SpeechStatus.

Remember, Kids could be visited by different visitors. It could allow any types of visitors to visit, however, the visitors should know what status needs to be updated for the kid after their visits.

Introduction

The Visitor Pattern could help us to decouple the operation details for a particular visitable object from multiple visitor objects. We isolate the responsibilities in the separate visitor objects(such as EyeDoctor, SLP & Parent) when those objects need to implement their own logic for the visitableObject(Kid).

This article introduces an implementation of how we use the visitor pattern to our daycare center.

Visitor Design Pattern Structure

visitorS.JPG

Class Diagram

VisitorClass.JPG - Click to enlarge image

Implementation Code

Visitor Objects

Visitor

Visitor class is our base abstract class. One abstract public method (Visit) has been declared in here to allow the child class to implement the details. It takes a VisitableObject object as the parameter. It actually provides the ability to the child Visitor class to work around it.

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

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public abstract class Visitor
        {
            abstract public void Visit(VisitableObject akid);
        }
    }
}

EyeDoctor

In my EyeDoctor class, a child Visitor class, it will only update the eyestatus for an incoming visitableObject.

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

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class EyeDoctor : Visitor
        {
            //Visit the visitableObject and update the deserved information
            public override void Visit(VisitableObject akid)
            {
                Kid kid = (Kid)akid;
                kid.EyeStatus = "Status updated from EyeDoctor - 
		Message from Dr.WANG, Eye Infections found for " + kid.Name + ". 
		Please schedule an appointment asap";
            }
        }
    }
}

SLP

Same as EyeDoctor, SLP class will only update the Speechstatus for an incoming visitableObject.

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

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class SLP : Visitor
        {

            public override void Visit(VisitableObject akid)
            {
                Kid kid = (Kid)akid;
                kid.SpeechStatus = "Status updated from SLP - This is Dr.FONG, " + 
			kid.Name + " did a good job on the speech exam.";
            }
        }
    }
}

Parent

Same as EyeDoctor, Parent class will update both Eyestatus and Speechstatus for an incoming visitableObject.

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

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class Parent : Visitor
        {
            public override void Visit(VisitableObject akid)
            {
                Kid kid = (Kid)akid;
                kid.EyeStatus += Environment.NewLine + 
			"Status updated from Parent -- This is " + kid.Name + 
			"'s parent, I updated the EyeStatus.";
                kid.SpeechStatus += Environment.NewLine + 
			"Status updated from Parent -- This is " + kid.Name + 
			"'s parent, I updated the SpeechStatus.";
            }
        }
    }
}

VisitableObject Class

VisitableObject

VisitableObject class is an abstract base class which has one public method(AcceptVisitor). AcceptVisitor method is the key method in our visitor pattern. It takes one Visitor object as the parameter, which will call its Visit function to visit visitableObject itself (an instance of visitableObject) in order to achieve the visit pattern.

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

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public abstract class VisitableObject
        {
            public void AcceptVisitor(Visitor visitor)
            {
                //allow the incoming visitor to start visiting
                visitor.Visit(this);
            }
        }
    }
}

Kid Class

Kid class in here is a helper class that inherits from the VisitableObject. It holds personal information for each child.

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

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class Kid : VisitableObject
        {
            public string Name { get; set; }
            public int Age { get; set; }

            public string EyeStatus { get; set; }
            public string SpeechStatus { get; set; }
        }
    }
}

Client App

From the client side, I create two kids as our visitableObject objects, and add them to the daycare. And I also create a visitor collection, it contains an EyeDoctor, a SLP and a Parent. For each kid, she/he will be visited by each visitor from the visitor collection.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.askbargains.com.VisitorDesignPattern;

namespace www.askbargains.com
{
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<kid> dayCare = new List<kid>();

                //Kid Elizabeth is created
                Kid Elizabeth = new Kid();
                Elizabeth.Name = "Elizabeth";
                Elizabeth.Age = 3;
                //add Elizabeth to daycare
                dayCare.Add(Elizabeth);

                //Kid Aimee is created
                Kid Aimee = new Kid();
                Aimee.Name = "Aimee";
                Aimee.Age = 4;
                //add Aimee to daycare
                dayCare.Add(Aimee);

                //create Visitors
                List<visitor> visitors = new List<visitor>();
                visitors.Add(new EyeDoctor());
                visitors.Add(new SLP());
                visitors.Add(new Parent());

                //start looping all the visitors
                foreach (Visitor visitor in visitors)
                {
                    //kid start to be visited for each visitor
                    foreach (Kid oneKid in dayCare)
                    {
                        oneKid.AcceptVisitor(visitor);
                    }
                }

                //display result
                foreach (Kid oneKid in dayCare)
                {
                    Console.WriteLine("Display Status for " + oneKid.Name);
                    Console.WriteLine(oneKid.EyeStatus);
                    Console.WriteLine(oneKid.SpeechStatus);
                    Console.ReadLine();
                }
                Console.ReadLine();
            }
        }
    }
}

Once we start our client app, you will see all that the correspond status has been updated after each visitor's visiting in the output window. Cool!

VisitorOutput.JPG

Conclusion

From this article, I demonstrated how we can use the Visitor Pattern to achieve the implementation for a Daycare visitor. I also use the daycare center for the Decorator Design pattern in my other article

License

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