Friday, July 10, 2009

Strategy Pattern

Definition:

The Gang of Four defines the Strategy in the following way,
"Define a family of algorithms, encapsulate each one,
and make them interchangeable.
Strategy lets the algorithm vary independently from clients that use it. "

Many developers who are new to design patterns will definitely get confused with this definition. Well, I will provide a simple explanation for this definition with an example.

Scenario

Let us assume a simple scenario that we have different classes for different kind of employees, Say, SoftwareEmployee, SalesEmployee and AccountingEmployee.  Now, all these classes needs have to implement SalaryRange which is a common method for all.  However, different employee type may have different salary schemes.  So implementing the SalaryRange is especially independent to the particular Employee type.

Solution

Overview of Strategy

In order to define the SalaryRange method in all the classes(SoftwareEmployee, SalesEmployee and AccountingEmployee), we define a interface with a method called SalaryRange which returns only string as follows(I made a simple implementation for demonstration purpose),

public interface IEmployee 

    string SalaryRange(); 
}

Now, let us implement this interface for all the employee types as follow,

public class SalesEmployee : IEmployee
    {
        string IEmployee.SalaryRange()
        {
            return "Depends on the target achieved";
        }

        //Some other members related to Sales person such as Area of Marketing,

//Product information, Sales Target

     }

    public class AccountingEmployee : IEmployee
    {
        string IEmployee.SalaryRange()
        {
            return "2000 - 8000";
        }

        //Some other members related to Accountants such as Method of Accounting

        //(manual or automated) etc. 
  }

Now each method(SalaryRange) is independent of it's own class.  So it has encapsulated its behavior with in the particular class that it belongs to.

The next goal is to create a concrete class that can communicate with all the Employee Types. Let us assume we have the class named as, SalaryRange with a method in the called SalaryRange as follows,

All we need to have in the SalaryRange class is to define a variable of type IEmployee.

IEmployee empType;
public SalaryRange()
        {
            //No implementation or provide default EmpType as
            this.EmpType = new SoftwareEmployee();
        }

        public SalaryRange(IEmployee empType)
        {
            this.EmpType = empType;
        }

        public IEmployee EmpType
        {
            set
            {
                empType = value;
            }
            get
            {
                return empType;
            }
        }


1. In this simple code we have a default constructor which will be called when the client wont send any type.
2. An Overloaded constructor which takes a single parameter of the type IEmployee.
3. Finally we define a Property to pass the value for IEmployee type.

The way we call the original method will be from the method getSalaryRange() defined in the SalaryRange class.

public string getSalaryRange()
        {
            if (empType != null)
                return empType.SalaryRange();
            else
                return "Employee type not specified..";
        }
This is a simple method which delegates it's call to the particular employee type dynamically.

We have now defined a Strategy which is an Interface called as IEmployee,
the ConcreteStrategy which are the classes SoftwareEmployee, SalesEmployee and AccountingEmployee.

Now we are going to write a asp.net page which acts as a client. In order to call get the
employee salary range of a particular employee we just need to define an object for the SalaryRange type.

This is the code in the Page Load event of our aspx page,

protected void Page_Load(object sender, EventArgs e)
   {
       SalaryRange softwareSalary = new SalaryRange();
       Response.Write("Software Engineer's Salary Varies " + softwareSalary.getSalaryRange());

       SalaryRange accountantSalary = new SalaryRange();
       accountantSalary.EmpType = new AccountingEmployee();
       Response.Write("<hr/>Accountant's Salary Varies " + accountantSalary.getSalaryRange());

       SalaryRange salesSalary = new SalaryRange(new SalesEmployee());
       Response.Write("<hr/>Sales Person's Salary Varies " + salesSalary.getSalaryRange());

       Response.Write("<hr/>");
   }

For the softwareSalary we are calling the default constructor where our default constructor will takes SoftwareEmployee type as its default.

AccountantSalary is implemented by using the Property.
SalesSalary is implemented by using the parameterized constructor.

In the Response.Write method we are just calling the getSalaryRange() method.  So here our client can call the SalaryRange class's getSalaryRange method as it likes.


kick it on DotNetKicks.com

No comments:

Post a Comment