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 Doctor
s.
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.