C# Design Patterns - The Visitor Pattern

What is the visitor pattern?

The visitor design pattern is a way of separating an algorithm from an object structure upon which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures. Thus, using the visitor pattern helps conformance with the open/closed principle [Wikipedia].

Our Requirements

One principle that I really like is the Open/Closed principle which says that an object should be open to new functionality but closed to structural changes. The visitor pattern helps facilitate this principle by giving us the means to perform operations against an object without changing the objects structure.

Looking back at a previous pattern we wanted to adjust the registration cost for a dog if they had been picked up by the dog catcher.

Implementing The Visitor

Supposing we have the implementation for the interface below we could use the visitor pattern to perform our tasks without changing the existing classes. Since we won’t be changing the existing implementation we don’t need to worry about breaking existing features. Lets assume that the repository returns 3 infractions for our dog in the code below.

internal interface IDog {
    int Id { get; set; }
    string Name { get; set; }
    string Breed { get; set; }
    string Address { get; set; }
    DateTime RegisterDate { get; set; }
    int RegistrationCost { get; set; }
    
ICollection<Infraction> Infractions { get; }
    void Accept(IVisitor visitor);
}

internal class Dog : IDog {
    private IRepository _repo;

    public Dog(IRepository repo) {
        _repo = repo;
        RegistrationCost = 25;
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Breed { get; set; }
    public string Address { get; set; }
    public DateTime RegisterDate { get; set; }
   
public int RegistrationCost { get; set; }
   
    public ICollection<Infraction> Infractions {
        get
{ return _repo.GetInfractions(Id); }
    }

    public void Accept(IVisitor visitor) {
        visitor.Visit(this);
    }
}

internal interface IVisitor {
    void Visit(IDog dog)
}

internal class Visitor : IVisitor {
    public Visitor() { }
    public void Visit(IDog dog) {
        var cost = dog.RegistrationCost;
        var infractions = dog.Infractions.Count;
        //increase cost $5 for each infraction
        dog.RegistrationCost = cost + (infractions * 5);
    }
}

So we have our dog class and we have our visitor setup. All we have left to do is execute it.

class Program {
    static void Main() {
       IDog dog = new Dog(Repository.Create<IDog>());
            IVisitor visitor = new Visitor();
            dog.Accept(visitor);
            Console.WriteLine(dog.RegistrationCost); //=> 40
   }
}

Conclusion

So just like the Decorator pattern, with the visitor pattern we can modify our class without changing the classes code. This pattern is more flexible because we can create any number of visitor classes to do just about anything without changing any code.

Be sure to grab the RSS feed, sign up for email updates, or follow me on Twitter to stay up to date and not miss any posts.

The C# Design Patterns Series

Part 1 - An Overview
Part 2 - The Decorator Pattern
Part 3 - The Abstract Factory Pattern
Part 4 - The Observer Pattern
Part 5 - The Facade Pattern
Part 6 - The Visitor Pattern

kick it on DotNetKicks.com Shout it

8 comments on this post

Apr 13, 2009 - 09:04:33

By having IDog instead of an inheritance hierarchy this example is really missing the point of the Visitor pattern in that it does not demonstrate double-dispatch. It also doesn’t demonstrate the structure correctly in that IDog doesn’t contain any child elements that are subsequently visited either.

[)amien

Steve says:
Apr 13, 2009 - 10:04:14

I’m sorry, but I find this example to be very lacking.

First, What benefit are you trying to illustrate? Wouldn’t a better example demonstrate using the visitor pattern to traverse a collection of objects in an interesting/ad-hoc way? For example, a visitor class could starts from one dog and and traverse his network of sexual partners and count the number of dogs in that network.

I don’t make much use of the visitor pattern, and this particular example doesn’t seem to demonstrate any good reasons to use it.

Apr 13, 2009 - 03:04:59

Hi,

I’ll come across your website and found it more interesting in Web Development. I learn more, thanks for the information you share, i’ll come back often.

Regards,

Dux Marketing

John says:
Apr 13, 2009 - 06:04:00

Thanks for the simple and clear explanation! This series is great. Keep them coming. :)

Christophe G says:
Apr 29, 2009 - 02:04:44

this post badly misses the point of the Visitor pattern: double-dispatch and encapsulation of the traversal of the object graph

Actually the pattern described here is the Strategy pattern, not the Vistitor pattern.

{ May 27, 2009 - 07:05:00 } Link Roundup :: eric.ness.net