Aug 17, 2013

Visitor Pattern

1 comment
The Visitor pattern is a powerful design pattern that I see a lot less than its popular brethren such as Factory, Facade, Command and Singleton. I believe this is because the pattern is often a bit more difficult for developers to understand and much of the articles and examples out there lack a real world example.

The Gang of Four defines the Visitor as:
Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

The very nature of the Visitor makes it an ideal pattern to plug into public API’s, thus allowing its clients to perform operations on a class using a “visiting” class without having to modify the source. Once familiar with this pattern, you will see the opportunity to apply it whenever you are dealing with composites or collections of interfaces/base classes.  

A Real World Example
I have been working on a project that uses a third-party application database. The database is very large and provides a set of base tables that are completely generic. These tables look much like what you find in SharePoint, with column names like CHAR_01, CHAR_02, DATE_01, DATE_02. The application adds meaning to these generic tables by creating Views with meaningful column names in the database to sit on top of them. For example, the EntryView will essentially map a field called BeginDate to the base table’s DATE_01 field.

A code generator has been written to interact with this database from .Net applications. The generator creates of class for each base table as well as a class for each view, which decorates the base table.

Here’s what that table/view structure looks coming out of the generator:
public class BaseTableRecord
{
    public int Int01 { get; set; }
    public string Char01 { get; set; }
    public bool Char02 { get; set; }
    public bool Bool01 { get; set; }
}
 
public abstract class PartyBaseView
{
    public PartyBaseView (BaseTableRecord record)
    {
        BaseRecord = record;
    }
 
    public BaseTableRecord BaseRecord { get; private set; }
}
 
public class PartyEntryView : PartyBaseView
{
    public PartyEntryView (BaseTableRecord record)
        : base(record)
    { }
 
    public int NumberInParty
    {
        get { return BaseRecord.Int01; }
        set { BaseRecord.Int01 = value; }
    }
 
    public string PartyName
    {
        get { return BaseRecord.Char01; }
        set { BaseRecord.Char01 = value; }
    }
}
 
public class PartyExitView : PartyBaseView
{
    public PartyExitView (BaseTableRecord record)
        : base(record)
    { }
 
    public int ExitingParty
    {
        get { return BaseRecord.Int01; }
        set { BaseRecord.Int01 = value; }
    }
 
    public string Payor
    {
        get { return BaseRecord.Char01; }
        set { BaseRecord.Char01 = value; }
    }
}

To remain generic, the primary type that is deal with is a collection of PartyViewBase types. Now there are all sorts of actions we will want to perform on these different views. Because any single Use Case could deal with a collection of PartyViewBase types, consisting of one or more instances of multiples PartyViewBase implementations, we need a way to interact with each inside an iteration without casting. A perfect example Use Case would be the need to map each view to an XML file. Let’s see how Visitor pattern (which will ultimately have to be added to the code generator) will work for me.

First I’m going to define the IPartyViewVisitor interface for my Visitor:
public interface IPartyViewVisitor
{
    void Visit(PartyEntryView view);
    void Visit(PartyExitView view);
}

Now I’m going to add a method to my PartyBaseView to allow the methods on my visitor to be invoked. Here’s what that abstract method looks like:
public abstract void Accept(IPartyViewVisitor vistor);

Here’s what the classes look like now that they’ve fully implemented the pattern:
public abstract class PartyViewBase
{
    public PartyViewBase(BaseTableRecord record)
    {
        BaseRecord = record;
    }
 
    public BaseTableRecord BaseRecord { get; private set; }
 
    public abstract void Accept(IPartyViewVisitor vistor);
}
 
public class PartyEntryView : PartyViewBase
{
    public PartyEntryView(BaseTableRecord record)
        : base(record)
    { }
 
    public override void Accept(IPartyViewVisitor vistor)
    {
        vistor.Visit(this);
    }
 
    public int NumberInParty
    {
        get { return BaseRecord.Int01; }
        set { BaseRecord.Int01 = value; }
    }
 
    public string PartyName
    {
        get { return BaseRecord.Char01; }
        set { BaseRecord.Char01 = value; }
    }
 
}
 
public class PartyExitView : PartyViewBase
{
    public PartyExitView(BaseTableRecord record)
        : base(record)
    { }
 
    public override void Accept(IPartyViewVisitor vistor)
    {
        vistor.Visit(this);
    }
 
    public int ExitingParty
    {
        get { return BaseRecord.Int01; }
        set { BaseRecord.Int01 = value; }
    }
 
    public string Payor
    {
        get { return BaseRecord.Char01; }
        set { BaseRecord.Char01 = value; }
    }
}

Next, I need to write an IPartyViewVisitor implementation to handle mapping my Views to XML files.
public class PartyViewMapperVisitor : IPartyViewVisitor
{
    //would take some infrastructure class in the constructor
 
    #region IPartyViewVisitor Members
 
    public void Visit(PartyEntryView view)
    {
        //do mapping here
        Console.WriteLine("Mapping PartyEntryView");
    }
 
    public void Visit(PartyExitView view)
    {
        //do maping here
        Console.WriteLine("Mapping PartyExitView");
    }
 
    #endregion
}

Now I’ll put it all together and get a list of PartyViewBase instances, loop through them, and let my Visitor implementation do the work
//instantiate my repository, service or whatever
PartyRepository repo = new PartyRepository();
 
//get my list of PartyViewBase instances
IList parties = repo.GetAllParties();
 
//instantiate my mapping visitor
PartyViewMapperVisitor visitor = new PartyViewMapperVisitor();
 
//loop through my PartyViewBase instances
foreach (var viewBase in parties)
{
     //perform my mapping
     viewBase.Accept(visitor);
}

Conclusion
The Visitor pattern allows you to define an operation on a class without changing that class. Because a Visitor is defined as an interface, visitor implementations can be written for multiple needs and the target class never gets touched, adhering to OCP. Whenever you are dealing with composites, think about using the Visitor pattern to make your life easier. It’s also great to stub the Visitor into public API’s to grant your clients, and yourself, future access without modification.

1 comment :