Sunday, September 29, 2013

Visitor Design Pattern

This article regarding a design pattern called Visitor. Even through this design pattern is not much popular in practical scenario. Let’s take a brief look at that. I’ll show you how I really understood this design pattern and how we can use it for real practical scenario.

Before going to further more let’s look at the definition

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.

In order to have a better picture of the design pattern let’s look at the UML of the Visitor pattern.


In this design pattern you can find 5 main objects. Those are
  • Object structure              
  • Element
  • Concrete Element
  • Visitor
  • Concrete Visitor
For the learning purpose I dived these 5 objects into 2 main parts. Object structure, Element and Concrete Element as one part and Visitor and Concrete Visitor as another. Next thing what we have to do is mapping pattern objects with real world objects. I will show you these mapping objects with some simple examples. But before that let’s see the big picture of the first three part



Object structure can have many different elements where these Object structure and Elements have strong relationship. And element might have different child element under them.

Object structure

This contain list or enumerable collection of Elements. This will be a high level interface to visitor to visit its Elements.  
Examples are Animals, Data types, Document and Employees 

Element

This is the smallest breaking part that object structure can represent if we break it. Important: that breaking parts can have different types but still it is a one breaking part. And the next key point is this contain a method called Accept. this method might be a definition or a implementation depend on the different types that available for the Element. Accept method accept any visitor to visit. 
Example
      • Animals - Birds | Mammals | Fishes | Reptiles
      • Data types - System.ValueType | System.Generic.Collections
      • Document - Document Part
      • Employees - Employee
                              this  categories might change depend on how you think to break it




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Employees d = new Employees();
            d.Attach(new Director(20000.025.0"Ivon"));
            d.Attach(new Developer(6000.010.0"Jackson"));
            d.SalaryDisplay();

            BonusVisitor htmlVisitor = new BonusVisitor();
            d.Accept(htmlVisitor);

            PrintEmployeeDetailVisitor printEmployeeDetailVisitor = new PrintEmployeeDetailVisitor();
            d.Accept(printEmployeeDetailVisitor);

            Console.ReadKey();
        }
    }

    public interface IVisitor
    {
        void Visit(Developer developer);
        void Visit(Director director);
    }

    public class BonusVisitor : IVisitor
    {
        public void Visit(Developer developer)
        {
            Console.WriteLine(string.Format("{0} - Salary With Bonus {1}"developer.Name , (developer.Salary * developer.bonusRate / 100+ developer.Salary - developer.Extra));
        }

        public void Visit(Director director)
        {
            Console.WriteLine(string.Format("{0} - Salary With Bonus {1}"director.Name , (director.Salary * director.bonusRate / 100+ director.Salary));
        }
    }

    public class PrintEmployeeDetailVisitor : IVisitor
    {
        public void Visit(Developer developer)
        {
            Console.WriteLine(string.Format("Employee Name : {0}\r\n Emplyee Salary{1}"developer.Namedeveloper.Salary));
        }

        public void Visit(Director director)
        {
            Console.WriteLine(string.Format("Employee Name : Director {0}\r\n Emplyee Salary{1}"director.Namedirector.Salary));
        }
    }


    public abstract class Employee
    {
        public double Salary { getset; }
        public double bonusRate { getset; }
        public string Name { getset; }
        public abstract void Accept(IVisitor visitor);
    }

    public class Director : Employee
    {
        public Director(double salarydouble bonusRatestring name)
        {
            this.Salary = salary;
            this.bonusRate = bonusRate;
            this.Name = name;
        }

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

    public class Developer : Employee
    {
        public double Extra { getset; }

        public Developer(double salarydouble bonusRatestring name)
        {
            this.Salary = salary;
            this.bonusRate = bonusRate;
            this.Name = name;
            this.Extra = 100.0;
        }

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

    public class Employees
    {
        private List<Employee> parts = new List<Employee>();

        public void Attach(Employee part)
        {
            parts.Add(part);
        }

        public void Deattach(Employee part)
        {
            parts.Remove(part);
        }

        public void SalaryDisplay()
        {
            parts.All(a => { Console.WriteLine(string.Format("{0} - Salary {1}"a.Namea.Salary.ToString())); return true; });
        }

        public void Accept(IVisitor visitor)
        {
            parts.All(a => { a.Accept(visitor); return true; });
        }
    }
sfsddfs