The Visitor pattern uses an external class to act on data in other classes. This is a useful approach to you when you have a polymorphic operation that cannot reside in the class hierarchy. Visitor is also a useful way to extend the behavior of a class hierarchy without the need to alter existing classes or to implement the new behavior in every subclass that requires it.
I think the visitor pattern feels a bit of a weird pattern. I mean weird in a way that it feels not very object-oriented nor structured way of programming. On the other hand, sometimes you have a collection of similar classes which differ in one or more methods. If you don’t want to ‘pollute’ your object-oriented hierarchy with these class-specific methods, then you can use the visitor pattern.
All the client needs is an object structure, a visitor and an element. One or more elements are attached to the object structure. The visitor visits the object structure and does ‘something’ with the attached elements.
class Client
{
static void Main()
{
ObjectStructure objectstructure = new ObjectStructure();
Element element = new ConcreteElement();
objectstructure.Attach(element);
ConcreteVisitor visitor = new ConcreteVisitor();
objectstructure.Accept(visitor);
Console.ReadKey();
}
}
The abstract class Visitor can have one or more concrete implementations, which do their work on the attached elements.
abstract class Visitor
{
public abstract void VisitConcreteElement(ConcreteElement concreteElement);
}
class ConcreteVisitor : Visitor
{
public override void VisitConcreteElement(ConcreteElement concreteElement)
{
Console.WriteLine("{0} visited by {1}", concreteElement.GetType().Name, this.GetType().Name);
}
}
The element class accepts a visitor and propagates an operation towards this visitor.
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
class ConcreteElement : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElement(this);
}
public void Operation()
{
}
}
The object structure contains all machinery needed for maintenance of a list of attached elements. In this way it resembles the subject class of the observer pattern.
class ObjectStructure
{
private List m_Elements = new List();
public void Attach(Element element)
{
m_Elements.Add(element);
}
public void Detach(Element element)
{
m_Elements.Remove(element);
}
public void Accept(Visitor visitor)
{
foreach (Element element in m_Elements)
{
element.Accept(visitor);
}
}
}
By now you should get some idea how the visitor pattern works.
Handy? I am not sure, I never used it in real life. What do you think. Please let me know.
This post is part of a series on the foundational design patterns in C#. In this series we explore the ancient design patterns and their use in real-world programming situations of today. In these series of posts we explore each pattern by looking at a minimalistic example to reveal its structure and then look at more concrete and useful real-world C# code that implements the pattern.