Friday 3 November 2017

Chain of responsibility Pattern

The chain of responsibility pattern can be thought of as a linked list, that receives input at the start of the list then propagates through a list until a node can handle it; once the input is "handled" it's done, it doesn't' continue on through the list. Think of it as an escalating issue that only goes as high as it needs to, for example if you need to expense a work lunch, odds are your direct manager can approve that expense, but let's say you need local training well maybe that group manager might have to approve it, or let's say it's training in a different country and you need a hotel room with travel, well then quite possibly the CFO might have to approve the expense.

think of it like this, in the chain of command each node has authority to approve an expense of a certain amount, if the expense surpasses that node's approval limit, the node must escalate the expense to the next level. let's take a look at the following

Line Manager (2000) -> Group Manager (3500) -> Regional Manager (10,000)-> CFO (50,000)-> CEO (*)

so in our scenario each level of management has the authority to approve expenses to a certain amount, once the request surpasses that amount, that level of management simply escalates the expense to the next level.

To get started we'll create the employee class, all our employee will do is represent an employee, for simplicity sake the only information we'll include in our employee is their name.

class Employee
{
    public string Name { get; set; }
    public Employee(string Name) => this.Name = Name;
}

next we'll create an ExpenseApprover class, normally we'd create an interface or abstract base class to enforce certain behavior, but for the sake of brevity we'll just make a standalone class.

class ExpenseApprover
{
    public Employee Employee { get; set; }
    public ExpenseApprover NextApprover { get; set; }
    public Double Limit { get; set; }

    public ExpenseApprover(Tuple<Employee, double> data)
    {
        this.Employee = data.Item1;
        this.Limit = data.Item2;
    }

    public bool Approve(double Expense)
    {
        if (Expense <= Limit)
        {
            Console.WriteLine($"Approved by {Employee.Name}");
            return true;
        }

        return NextApprover == null ? false : NextApprover.Approve(Expense);
    }
}

This class has a reference to the employee, their spending limit and a pointer to the next approver in the chain of command as well as a recursive approve function. In our approve function if the expence can be approved by the current employee it is, otherwise it's escalated to the next approver.

Now let's look at the main

class Program
{
    static void Main(string[] args)
    {
        Tuple<Employee, double>[] Employees = {
            new Tuple<Employee, double>(new Employee("Line Manager"), 100.0),
            new Tuple<Employee, double>(new Employee("Group Manager"), 200.0),
            new Tuple<Employee, double>(new Employee("Reginal Manager"), 500.0),
            new Tuple<Employee, double>(new Employee("CFO"), 1000.0),
            new Tuple<Employee, double>( new Employee("CEO"), 2000.0)};

        var LineManager = new ExpenseApprover(Employees[0]);
        var currManager = LineManager;

        for (int i = 1; i < Employees.Length; i++)
        {
            currManager.NextApprover = new ExpenseApprover(Employees[i]);
            currManager = currManager.NextApprover;
        }

        LineManager.Approve(400);
    }
}

simple enough, we create a reference  to the first node in our chain, then within the loop we build our chain. then when we submit our expense to our first node, if it can handle it, it does otherwise it passes it to the next node in the chain and so on, till their are no more nodes. now we could have created a final terminating node with some sort of business logic, but for a trivial reminder, it seemed like a bit overkill.