Thursday, May 30, 2013

Decorator Pattern - with simple example

In general it is hard for guys to understand different design patterns. Decorator design pattern is one even though simple it is bit tricky to understand. To make it simple I have taken a simple example to calculate selling price of 1 kg of SUGAR from manufacturing to hand of buyer. Also, consider selling of 1 kg of sugar in 2 different states. Just consider sugar is manufactured in state JKL.

Lets consider following scenario for both the states:
  1. Manufacturing and Packaging Cost of 1 kg sugar in JKL state = $ 15.00
  2. Transportation Cost = in state ABC is $ 25.00; in state XYZ is $ 23.00
  3. Retail Shop Profit = in state ABC is $ 23.00; in state XYZ is $ 31.22
  4. Sales Tax = in state ABC is 11 %; in state XYZ is 21 %
Now, lets implement this scenario using Decorator Design Pattern and find out Selling Price. But before that let understand the idea behind this design pattern. 

Wiki Says The decorator pattern can be used to extend (decorate) the functionality of a certain object statically, or in some cases at run-time, independently of other instances of the same class, provided some groundwork is done at design time. This is achieved by designing a new decorator class that wraps the original class.

Everything start with a base class and simple abstract method
public abstract class Base
{
    public abstract double Cost();
}

Use the base class to implement the base object to calculate manufacturing cast of 1 kg of sugar in state JKL
public class SugarBasePrice : Base
{
    public override double Cost()
    {
        Console.WriteLine("1 kg Sugar Base Price cost = 15.00");
        return 15.00;
    }
}

Now, there are additional decoration i.e. expenses needed to be added. But we know now an then additional taxes or expenses added on it. To take care of it without tampering with existing existing implementation will implement decorator base class inherited from product base class.
public abstract class AdditionalExpense : Base
{
    protected Base BaseObj { get; set; }
    public AdditionalExpense(Base b)
    {
        Console.WriteLine("AdditionalExpense constructor");
        BaseObj = b;
    }
}

Now, inherit the decorator base class and implement the different decorator classes for state ABC (refer to example given above).
public class TransportationCost2ABC : AdditionalExpense
{
    public TransportationCost2ABC(Base b)
        : base(b)
    {
        Console.WriteLine("TransportationCost2ABC constructor");
    }
    public override double Cost()
    {
        double d = 25.00 + BaseObj.Cost();
        Console.WriteLine("with Transportation Cost to ABC cost = " + d);
        return d;
    }
}
public class RetailShopProfitInABC : AdditionalExpense
{
    public RetailShopProfitInABC(Base b)
        : base(b)
    {
        Console.WriteLine("RetailShopProfitInABC constructor");
    }
    public override double Cost()
    {
        double d = 23.00 + BaseObj.Cost();
        Console.WriteLine("with Retail Shop Profit In ABC cost = " + d);
        return d;
    }
}
public class SalesTaxInABC : AdditionalExpense
{
    public SalesTaxInABC(Base b)
        : base(b)
    {
        Console.WriteLine("SalesTaxInABC constructor");
    }
    public override double Cost()
    {
        double d = BaseObj.Cost();
        d += (d * 0.11);
        Console.WriteLine("with Sales Tax In ABC cost = " + d);
        return d;
    }
}

Now, implement it for state XYZ (refer to example given above).
public class TransportationCost2XYZ : AdditionalExpense
{
    public TransportationCost2XYZ(Base b)
        : base(b)
    {
        Console.WriteLine("TransportationCost2XYZ constructor");
    }
    public override double Cost()
    {
        double d = 23.00 + BaseObj.Cost();
        Console.WriteLine("with Transportation Cost to XYZ cost = " + d);
        return d;
    }
}
public class RetailShopProfitInXYZ : AdditionalExpense
{
    public RetailShopProfitInXYZ(Base b)
        : base(b)
    {
        Console.WriteLine("RetailShopProfitInXYZ constructor");
    }
    public override double Cost()
    {
        double d = 31.22 + BaseObj.Cost();
        Console.WriteLine("with Retail Shop Profit In XYZ cost = " + d);
        return d;
    }
}
public class SalesTaxInXYZ : AdditionalExpense
{
    public SalesTaxInXYZ(Base b)
        : base(b)
    {
        Console.WriteLine("SalesTaxInXYZ constructor");
    }
    public override double Cost()
    {
        double d = BaseObj.Cost();
        d += (d * 0.21);
        Console.WriteLine("with Sales Tax In XYZ cost = " + d);
        return d;
    }
}

I think it is still not clear how will this implementation works. To understand, if you have seen the code above there are many break points added to display in console regarding when the constructors and cost method fires. Following is the console application implementation and output. Observe the output carefully, you will see the invocation of different constructor and calculations:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("********* State ABC Details ************");
            Base BB = new SugarBasePrice();
            BB = new TransportationCost2ABC(BB);
            BB = new RetailShopProfitInABC(BB);
            BB = new SalesTaxInABC(BB);
            Console.WriteLine("Sale Price of 1 Kg Sugar in ABC state = " + BB.Cost());
            Console.WriteLine("********* State XYZ Details ************");
            Base CC = new SugarBasePrice();
            CC = new TransportationCost2XYZ(CC);
            CC = new RetailShopProfitInXYZ(CC);
            CC = new SalesTaxInXYZ(CC);
            Console.WriteLine("Sale Price of 1 Kg Sugar in XYZ state = " + CC.Cost());
            Console.ReadLine();
        }
    }
}

Console Output
********* State ABC Details ************             
AdditionalExpense constructor                        
TransportationCost2ABC constructor                   
AdditionalExpense constructor                        
RetailShopProfitInABC constructor                    
AdditionalExpense constructor                        
SalesTaxInABC constructor                            
1 kg Sugar Base Price cost = 15.00                   
with Transportation Cost to ABC cost = 40            
with Retail Shop Profit In ABC cost = 63             
with Sales Tax In ABC cost = 69.93                   
Sale Price of 1 Kg Sugar in ABC state = 69.93        
********* State XYZ Details ************             
AdditionalExpense constructor                        
TransportationCost2XYZ constructor                   
AdditionalExpense constructor                        
RetailShopProfitInXYZ constructor                    
AdditionalExpense constructor                        
SalesTaxInXYZ constructor                            
1 kg Sugar Base Price cost = 15.00                   
with Transportation Cost to XYZ cost = 38            
with Retail Shop Profit In XYZ cost = 69.22          
with Sales Tax In XYZ cost = 83.7562                 
Sale Price of 1 Kg Sugar in XYZ state = 83.7562      

4 comments:

  1. Nice explaination

    ReplyDelete
  2. Nice info regarding decoratorator pattern in dotnet My sincere thanks for sharing this post Please Continue to share this post
    Dot Net Training in Chennai

    ReplyDelete
  3. nice blog has been shared by you. before i read this blog i didn't have any knowledge about this but now i got some knowledge. so keep on sharing such kind of an interesting blog.
    dotnet training in chennai

    ReplyDelete