Use Explicit Interface Implementation to Hide Visitor Traversal

The Visitor Design Pattern is a great way to separate your model data and relationships from the operations you want to perform on that data. However, there are some downsides to using it, one of which we can mitigate by taking advantage of explicit interface implementation in C#.

The visitor pattern in use

I recently used the pattern in a code sample for a blog post describing a technical test strategy. The domain model consisted of roles in an organisation and a visitor pattern was used to perform operations on that data:

Visitor

This is a great example of the Open Closed Principle at work. The functionality of the model can be extended by adding new visitors without modifying existing code.

Spreading the knowledge

There are a couple of obvious disadvantages of the pattern that threaten to undo the benefits described above. The first being that the IVisitor interface has to know what domain types exist and hence all visitors are subject to change whenever types are added, deleted or updated. If you are confident that your traversable types will change infrequently, then this is a small price to pay.

Our types on the other hand need to know that they are candidates for visitor traversal and implement the Accept method. Although this is not desirable, again it is not typically a huge problem as the implementation rarely changes.

Cleaning up the public interface

The Accept method needs to be publicly/internally accessible, however this means that these key domain types which are probably used throughout the application, leak details of the pattern wherever they are used:

intellisenseWithAcceptMethod

By creating an IVisitable interface, we can then use explicit interface implementation to hide Accept from anyone who doesn’t know the type as an IVisitable (ie. only the visitors themselves):

void IVisitable.Accept(IVisitor visitor)
{
    visitor.Visit(this);
    foreach (var employee in Subordinates)
    {
        ((IVisitable)employee).Accept(visitor);
    }
}

Which means that in typical use, this design choice is no longer exposed to the rest of the world:

intellisenseWithoutAccept

While this obviously doesn’t solve all of the downsides to using the visitor pattern, it goes a step further to hiding its use. You can check out the full example here.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s