Decorator Design Pattern in C#

Decorator patterns is one of the most popular patterns. It's a behavioral patterns and are used when we want to add dynamic behavior to some object, but we don't want to change that Class. It is basically used in Legacy systems, Sealed Classes. Decorator pattern follows open closed principle i.e. Closed for modification and open for extension.                         

The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. 
(Head First Design Patterns, O'Reilly)

The decorator pattern can be used to extend (decorate) the functionality of a certain object 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. 
(Wikipedia, http://en.wikipedia.org/wiki/Decorator_pattern)


A simplified UML diagram for the Decorator Pattern is shown in following Figure:-   

Decorator-Design-Pattern-1.jpg 
                                              
I am describing it through a sample application. In my sample application, There are different size of pizza. Now pizza maker company decides to give add-ons like cheese, chicken, pepper depending upon what customer prefer. Some customers want chicken pizza, some want cheese, some want cheese and pepper. If we use classical inheritance, there would be class explosion. 

Structure of my application is shown in the image:-

Decorator-Design-Pattern-2.jpg

There are four components in my solution- 1. Component (It can be interface or abstract class)  2. ConcreteComponent  3. Decorator ( It will contain instance of component) 4. Concrete Decorator

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace Decorator

{

    class Program

    {

        static void Main(string[] args)

        {

            Pizza pizza = new LargePizza();

            pizza = new CheeseDecorator(pizza);

            pizza = new PepprDecorator(pizza);

            pizza = new ChickenDecorator(pizza);

            Console.WriteLine(pizza.GetDescription());

            Console.WriteLine(pizza.GetCost());

            Console.ReadLine();

        }

    }

}
 

---------------------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace Decorator

{

   public  class LargePizza : Pizza

    {

        public LargePizza()

        {

            Description = "It is Large Pizza";

        }

        public override string GetDescription()

        {

            return Description;

        }

        public override double GetCost()

        {

            return 5;

        }

    }

}

 

------------------------------------------------------------------------------------------------------------------------
 

namespace Decorator

{

    class MediumPizza : Pizza

    {

        public MediumPizza()

        {

            Description = "It is Medium Pizza";

        }

        public override string GetDescription()

        {

            return Description;

        }

        public override double GetCost()

        {

            return 4;

        }

    }

}

 

------------------------------------------------------------------------------------------------------------------------
 

namespace Decorator

{

    class SmallPizza : Pizza

    {

        public SmallPizza()

        {

            Description = "It is Small Pizza";

        }

        public override string GetDescription()

        {

            return Description;

        }

        public override double GetCost()

        {

            return 3;

        }

    }

}
 

------------------------------------------------------------------------------------------------------------------------
 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace Decorator

{

   public class Decorator : Pizza

    {

        public Pizza _pizza;

        public Decorator(Pizza pizza)

        {

            _pizza = pizza;

        }

        public override string GetDescription()

        {

            return _pizza.GetDescription();

        }

        public override double GetCost()

        {

            return _pizza.GetCost();

        }

    }

}

 

------------------------------------------------------------------------------------------------------------------------
 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace Decorator

{

    public class CheeseDecorator:Decorator

    {

        public CheeseDecorator(Pizza pizza)

            : base(pizza)

        {

            Description = "Cheese Added";

        }

        public override string GetDescription()

        {

            return _pizza.GetDescription() + Description;

        }

        public override double GetCost()

        {

            return _pizza.GetCost() + 1 ;

        }

    }

}

 

------------------------------------------------------------------------------------------------------------------------
 

using System.Text;

 

namespace Decorator

{

    public class PepprDecorator : Decorator

    {

        public PepprDecorator(Pizza pizza)

            : base(pizza)

        {

            Description = "Pepper Added";

        }

        public override string GetDescription()

        {

            return _pizza.GetDescription() + Description;

        }

        public override double GetCost()

        {

            return _pizza.GetCost() + 1.1;

        }

    }

}
 

------------------------------------------------------------------------------------------------------------------------
 

using System.Text;

 

namespace Decorator

{

    public class ChickenDecorator : Decorator

    {

        public ChickenDecorator(Pizza pizza)

            : base(pizza)

        {

            Description = "Chicken Added";

        }

        public override string GetDescription()

        {

            return _pizza.GetDescription() + Description;

        }

        public override double GetCost()

        {

            return _pizza.GetCost() + 1.1;

        }

    }

}