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
Class Diagram
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.
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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace VisitorDesignPattern
{
public class EyeDoctor : Visitor
{
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.
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.
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.
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)
{
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.
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.
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 = new Kid();
Elizabeth.Name = "Elizabeth";
Elizabeth.Age = 3;
dayCare.Add(Elizabeth);
Kid Aimee = new Kid();
Aimee.Name = "Aimee";
Aimee.Age = 4;
dayCare.Add(Aimee);
List<visitor> visitors = new List<visitor>();
visitors.Add(new EyeDoctor());
visitors.Add(new SLP());
visitors.Add(new Parent());
foreach (Visitor visitor in visitors)
{
foreach (Kid oneKid in dayCare)
{
oneKid.AcceptVisitor(visitor);
}
}
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!
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.