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:-
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:-
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;
}
}
}