Definition
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
UML class diagram
Participants
The classes and/or objects participating in this pattern are:
- Visitor - declares a Visit operation for each class of ConcreteElement in the object structure. The operation's name and signature identifies the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the elements directly through its particular interface
- ConcreteVisitor - implements each operation declared by Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class or object in the structure. ConcreteVisitor provides the context for the algorithm and stores its local state. This state often accumulates results during the traversal of the structure.
- Element - defines an Accept operation that takes a visitor as an argument.
- ConcreteElement - implements an Accept operation that takes a visitor as an argument
- ObjectStructure
may provide a high-level interface to allow the visitor to visit its elements
may either be a Composite (pattern) or a collection such as a list or a set
Sample code in C#
#region Visitor
public interface IVisitor
{
#region Methods
void Visit(Element element);
#endregion
}
#endregion
#region Visitor Concrete
public class VisitorConcreteA : IVisitor
{
#region IVisitor Members
public void Visit(Element element)
{
Console.WriteLine("{0} Visited {1}", this.GetType().Name, element.GetType().Name);
}
#endregion
}
public class VisitorConcreteB : IVisitor
{
#region IVisitor Members
public void Visit(Element element)
{
Console.WriteLine("{0} Visited {1}", this.GetType().Name, element.GetType().Name);
}
#endregion
}
#endregion
#region Element
public interface IElement
{
void Accept(IVisitor visitor);
}
public abstract class Element : IElement
{
#region IElement Members
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
#endregion
}
#endregion
#region Concrete Element
public class ElementConcreteA : Element
{
// implement whatever you need
}
public class ElementConcreteB : Element
{
// implement whatever you need
}
#endregion
#region Object Structure
public class ObjectStructure
{
#region Members
private List_elements;
#endregion
#region Ctor
///
/// Construct a new object structure
///
public ObjectStructure()
{
_elements = new List();
}
#endregion
#region Methods
///
/// Attach the given element to the object structure
///
/// The element to attach
public void AttachElement(Element element)
{
_elements.Add(element);
}
///
/// Detaches the given element from the object structure
///
/// The element to detach
public void DetachElement(Element element)
{
_elements.Remove(element);
}
///
/// Perform accept operation on all the object structure
/// with the given visitor
///
/// The given visitor
public void Accept(IVisitor visitor)
{
foreach (Element element in _elements)
{
element.Accept(visitor);
}
}
#endregion
}
#endregion
In the example I use an object structure that is implemented with an inner list. You can use whatever object structure you need in order to implement the pattern. As can be seen in the example, I use two main interfaces to implement the pattern – IVisitor and IElement. The IElement dictates the Accept method to the Element abstract class which every concrete element implement (I could drop the IElement or the Element class but I have chosen not to). Every visitor concrete implement the Visit operation to perform the desired operation (in my implementation the Visit method is implement the same in both concrete classes).
The next code shows an example of how to use the classes above:
// Build the structure
ObjectStructure structure = new ObjectStructure();
structure.AttachElement(new ElementConcreteA());
structure.AttachElement(new ElementConcreteB());
// Create visitor objects
VisitorConcreteA visitorA = new VisitorConcreteA();
VisitorConcreteB visitorB = new VisitorConcreteB();
// Structure accepting visitors
structure.Accept(visitorA);
structure.Accept(visitorB);
Console.Read();
-
-
Liest(1770)
-
Permalink