Objective ๐ฏ
Provide a way of separating an algorithm from an object allowing to add/change operations at run time.
Type โ
โ๏ธBehavioral: Describes how objects interact/communicate between themselves.
โCreational: Describes how to instantiate an object without large and complex.
โStructural: Describes how objects/classes are composed to form larger structures.
UML ๐
Participants ๐
โข Visitor:
- Declares a specific method (Visit) for each ConcreteElement in the Object Structure
โข ConcreteVisitor:
- Implements each operation declared in the Visitor
โข Element:
- Defines an Accept method that receives a Visitor as an argument
โข ConcreteElement:
- Implements the Element's interface
โข ObjectStructure:
- Maintains a list of elements
- Provides an interface to attach and remove elements in the list
Sample Code ๐ฎ
Structural Example ๐๏ธ
namespace Main.Visitor
{
public static class VisitorStructural
{
public static void Execute()
{
ObjectStructure lObjectStructure = new ObjectStructure();
lObjectStructure.Attach(new ConcreteElementA());
lObjectStructure.Attach(new ConcreteElementB());
ConcreteVisitor1 lConcreteVisitor1 = new ConcreteVisitor1();
ConcreteVisitor2 lConcreteVisitor2 = new ConcreteVisitor2();
lObjectStructure.Accept(lConcreteVisitor1);
lObjectStructure.Accept(lConcreteVisitor2);
}
}
public abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA prConcreteElementA);
public abstract void VisitConcreteElementB(ConcreteElementB prConcreteElementB);
}
public class ConcreteVisitor1 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA prConcreteElementA)
{
Console.WriteLine("{0} visited by {1}",
prConcreteElementA.GetType().Name, this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB prConcreteElementB)
{
Console.WriteLine("{0} visited by {1}",
prConcreteElementB.GetType().Name, this.GetType().Name);
}
}
public class ConcreteVisitor2 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA prConcreteElementA)
{
Console.WriteLine("{0} visited by {1}", prConcreteElementA.GetType().Name, this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB prConcreteElementB)
{
Console.WriteLine("{0} visited by {1}", prConcreteElementB.GetType().Name, this.GetType().Name);
}
}
public abstract class Element
{
public abstract void Accept(Visitor prVisitor);
}
public class ConcreteElementA : Element
{
public override void Accept(Visitor prVisitor)
{
prVisitor.VisitConcreteElementA(this);
}
}
public class ConcreteElementB : Element
{
public override void Accept(Visitor prVisitor)
{
prVisitor.VisitConcreteElementB(this);
}
}
public class ObjectStructure
{
private List<Element> _Elements = new List<Element>();
public void Attach(Element prElement)
{
_Elements.Add(prElement);
}
public void Detach(Element prElement)
{
_Elements.Remove(prElement);
}
public void Accept(Visitor prVisitor)
{
foreach (Element lElementCurrent in _Elements)
{
lElementCurrent.Accept(prVisitor);
}
}
}
}
Output
Real-world Example ๐ฅ
public static class VisitorPractical
{
public static void Execute()
{
School lSchool = new School();
lSchool.Attach(new Student() { _Name = "Frank" });
lSchool.Attach(new Student() { _Name = "Matt" });
lSchool.Attach(new Student() { _Name = "Jennifer" });
lSchool.Accept(new Doctor());
lSchool.Accept(new CarrerCoach());
}
}
public interface IVisitor
{
public void Visit(Student prStudent);
}
public interface IElement
{
public void Accept(IVisitor prVisitor);
}
public class Student : IElement
{
public string _Name { get; set; }
public void Accept(IVisitor prVisitor)
{
prVisitor.Visit(this);
}
}
public class Doctor : IVisitor
{
public void Visit(Student prStudent)
{
Console.WriteLine($"Student \"{prStudent._Name}\" visited by {this.GetType().Name}");
}
}
public class CarrerCoach : IVisitor
{
public void Visit(Student prStudent)
{
Console.WriteLine($"Student \"{prStudent._Name}\" visited by {this.GetType().Name}");
}
}
public class School
{
private List<Student> _Students = new List<Student>();
public void Attach(Student prStudent)
{
_Students.Add(prStudent);
}
public void Detach(Student prStudent)
{
_Students.Remove(prStudent);
}
public void Accept(IVisitor prVisitor)
{
foreach (Student lStudentCurrent in _Students)
{
lStudentCurrent.Accept(prVisitor);
}
}
}
Output
Source Code ๐ฒ
ย