The visitor design pattern allows us to separate an algorithm from the structure that the algorithm works against. This is one of the easiest ways to adhere to the open/closed principle. because it allows us to add new algorithms without having to modify the original structure that the algorithm is run against.

The full source code for this entry can be downloaded from here.

The visitor design pattern core interfaces in C#:

1 public interface IVisitable<T>
2     {
3       void accept(IVisitor<T> visitor);
4     }
5 
6     public interface IVisitor<T>
7     {
8       void visit(T item);
9     }

example

In the following example, I’ve defined a structure for a table. A table has many rows, and each row has a different cell for each column.

I have omitted a lot of details for brevity.

 1 public class Table : IVisitable<Row>
 2     {
 3         ...
 4         public void accept(IVisitor<Row> visitor)
 5         {
 6             rows.each(x => visitor.visit(x));
 7         }
 8     }
 9 
10     public class Row : IVisitable<ICell>
11     {
12         ...
13         public void accept(IVisitor<ICell> visitor)
14         {
15             cells.each(x => visitor.visit(x));
16         }
17     }
18 
19     public class Column<T> : IColumn
20     {
21         ...
22         public Column(string name)
23         {
24             this.name = name;
25         }
26     }
27 
28     public class Cell<T> : ICell
29     {
30         ...
31         public bool IsFor(IColumn otherColumn)
32         {
33             return column.Equals(otherColumn);
34         }
35 
36         public T Value { get; private set; }
37 
38         public void ChangeValueTo(T value)
39         {
40             Value = value;
41         }
42     }

We can now define different algorithms for traversing the table structure without having to modify the table structure. In this example the TotalRowsVisitor increments a counter each time it visits a row.

 1 public class TotalRowsVisitor : IVisitor<Row>
 2     {
 3         public void visit(Row item)
 4         {
 5             Total++;
 6         }
 7 
 8         public int Total { get; set; }
 9     }
10 
11     var visitor = new TotalRowsVisitor();
12     table.accept(visitor);
13     Console.Out.WriteLine( visitor.Total );

The full source code for this entry can be downloaded from here.

comments powered by Disqus