Description
A decorator design pattern allows you to modify an object an it’s capabilities dynamically. It’s more flexible then classical inheritance because you can compose more functionalities on the fly.
A decorator imposes creating a base object. The decorator on top of the base objects rewrites some of the functionality by taking in account the new option added.
Let’s consider we have a pizza place. We start by defining the base pizza, this would be our component
public interface IPizza { string getDescription(); double getCost(); } public class PlainPizza : IPizza { public virtual double getCost() { return 4; } public virtual string getDescription() { return "thin"; } }
The abstract decorator class on top of the decorator will return also an IPizza type. It takes in a predefined pizza type an add extra toppings on it.
Decorator Base Class
public class ToppingDecorator : IPizza { protected IPizza tempPizza; public ToppingDecorator(IPizza refPizza) { this.tempPizza = refPizza; } public virtual double getCost() { return tempPizza.getCost(); } public virtual string getDescription() { return tempPizza.getDescription(); } }
Concrete decorators
public class Tomatto : ToppingDecorator { public Tomatto(IPizza refPizza) : base(refPizza) { Console.WriteLine("Adding Sauce"); } public override double getCost() { return tempPizza.getCost() + 0.25; } public override string getDescription() { return tempPizza.getDescription() + ", Tomato"; } } public class Mozarella : ToppingDecorator { public Mozarella(IPizza refPizza) : base(refPizza) { //Console.WriteLine("Adding Dough"); //Console.WriteLine("Adding mozarella"); } public override double getCost() { return tempPizza.getCost() + 0.5; } public override string getDescription() { return tempPizza.getDescription() + ", Mozarella"; } }
Now all you have to do is just define what you kind of toppings you want to your pizza. The implementation is simple, although I find that this induces a high degree of “over-constructing”.
static void Main(string[] args) { PlainPizza basic = new PlainPizza(); Tomatto cool = new Tomatto(new Mozarella(new PlainPizza())); Console.WriteLine(basic.getCost()); Console.WriteLine(basic.getDescription()); Console.WriteLine("---"); Console.WriteLine(cool.getCost()); Console.WriteLine(cool.getDescription()); }