Visitor design pattern lets you to define a
new operation without changing or modifying its existing classes. Visitor
Pattern falls under behavioral pattern of GOF (Gang of Four) patterns.
When to use –
Visitor pattern can use when we want to
perform an operation on similar kind of objects. Using visitor pattern we can add
new functionality to the original objects or hierarchy or objects via Visitor
subclass.
Visitor pattern consist of main two
methods. One method is Visit() which is called for every element in the object
hierarchy. Second method is Accept() which is implemented by the class who is
visiting object hierarchy and accepted by visitors.
Major components of Visitor pattern –
Visitor – This
is an interface declares Visit operation.
Concrete Visitor – This class implements Visitor interface and implements visit
operation.
Element – This
is an interface declares the Accept operation which takes visitor as an argument.
Concrete Element – This class implements Element interface and implements Accept operation.
Client – Client
is an entry point class that has access to data structure objects and process
elements to visit object hierarchy.
Let’s have a look on below example of Visitor
design pattern.
Code –
public enum Categories
{
Food,
Oil,
Electronics,
Cloths
}
//element
public interface IElement
{
void Accept(IVisitor visitor);
}
//concrete element
public class Products : IElement
{
public void Accept(IVisitor visitor)
{
Console.WriteLine("Name - {0}, Product Visited - {1}, Category -
{2}",
visitor.Name,
visitor.ProductVisited, visitor.Category);
}
}
//concrete element
public class Discounts : IElement
{
public void Accept(IVisitor visitor)
{
double discount = 0;
switch (visitor.Category)
{
case Categories.Food:
discount = 10;
break;
case Categories.Electronics:
discount = 20;
break;
case Categories.Cloths:
discount = 15;
break;
default:
discount = 5;
break;
}
Console.WriteLine("Product Name - {0}, Price - {1}, Discount
({2}%) - {3}",
visitor.ProductVisited,
visitor.Price, discount, (visitor.Price * discount)/100);
}
}
//visitor
public interface IVisitor
{
string Name { get; set; }
string ProductVisited { get; set; }
double Price { get; set; }
Categories Category { get; set; }
void Visit(IElement element);
}
//concrete visitor
public class GroceriesVisitor : IVisitor
{
public string Name { get; set; }
public string ProductVisited { get; set; }
public double Price { get ; set; }
public Categories Category { get; set; }
public GroceriesVisitor(string name, string productVisited, double price, Categories category )
{
Name = name;
ProductVisited = productVisited;
Price = price;
Category = category;
}
public void Visit(IElement element)
{
element.Accept(this);
}
}
//concrete visitor
public class AppliancesVisitor : IVisitor
{
public string Name { get; set; }
public string ProductVisited { get; set; }
public double Price { get; set; }
public Categories Category { get; set; }
public AppliancesVisitor(string name, string productVisited, double price, Categories category)
{
Name = name;
ProductVisited = productVisited;
Price = price;
Category = category;
}
public void Visit(IElement element)
{
element.Accept(this);
}
}
//concrete visitor
public class FashionVisitor : IVisitor
{
public string Name { get; set; }
public string ProductVisited { get; set; }
public double Price { get; set; }
public Categories Category { get; set; }
public FashionVisitor(string name, string productVisited, double price, Categories category)
{
Name = name;
ProductVisited = productVisited;
Price = price;
Category = category;
}
public void Visit(IElement element)
{
element.Accept(this);
}
}
//entry point
class Program
{
static void Main(string[] args)
{
List<IVisitor> Items = new List<IVisitor>();
Items.Add(new GroceriesVisitor("Visitor1", "Rice", 150, Categories.Food));
Items.Add(new GroceriesVisitor("Visitor2", "Oil", 95, Categories.Oil));
Items.Add(new AppliancesVisitor("Visitor3", "Speakers", 500, Categories.Electronics));
Items.Add(new AppliancesVisitor("Visitor4", "Cameras", 500, Categories.Electronics));
Items.Add(new FashionVisitor("Visitor5", "Shirts", 1500, Categories.Cloths));
Items.Add(new FashionVisitor("Visitor6", "Jeans", 3000, Categories.Cloths));
Console.WriteLine("-----Visiting prices of all items-----");
foreach(var item in Items)
{
item.Visit(new Products());
}
Console.WriteLine("-----Visiting discounts of all
items-----");
foreach (var item in Items)
{
item.Visit(new Discounts());
}
Console.Read();
}
}
Output –
As per above example, there are many
visitor and elements defined. Different type of visitors visits various products.
In this example Product object allows different visitor to visit product
related information like Product Name, category etc. where Discount object
allows different visitor to visit discounts available on various categories of
products.
You can download full code from Gist.
I hope this article helps you to know more
about Visitor Design Pattern. Please leave your feedback in comments section
below.
References –
See Also –
Creational Patterns
|
Structural Patterns
|
Behavioral Patterns
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|