It all started with this article posted by a good friend of mine about his way of implementing the factory pattern.

Although there is nothing to approach about his way, something kept itching me to write a second article about another design pattern that might fit in this situation as well.

Let’s start by reviewing the task:

The Straw hats pirates (the pirate crew in the one piece anime) contacted my company to write a software to automate pizza preparation. Sanji explained that in order to prepare pizza we need to:

  1. Prepare the Pizza Dough
  2. Prepare the sauce
  3. Add pizza sauce and pizza ingredients according to each person’s desires
  4. Put the pizza in the oven

In order to complete the task, my friend wrote a Pizza maker base class where inherited classes redefine the AddIngredient Method to suit each person’s choices.

Proposed solutionProposed solution

For example, if the person is Nami then ingredients will be cheese and olives. To add his own touch, my friend added a configuration section to make class adding totally on the fly. There is no doubt that the solution is flexible and neat but what happens when more people joins in the team? Or when current crew feels like tasting something new? Are we going to create sub classes for each possibility like this:

Future problemFuture problem

It’s sure not a good solution because with 3 ingredients (Olive, cheese and meat) we can have up to 7 different combinations (result = n! / [(n-k)! k!] Where n is total number of ingredients and k is the number of the picked ingredients), Imagine what will happen with 4 or 5 ingredients => explosion in number of sub classes.

What should we do then? It’s time to introduce the Decorator Pattern!

The decorator pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Wikipedia

Don’t worry if you don’t understand this, I myself didn’t when I first read it but this example will help clear things for us.

Decorator patternDecorator pattern

Component: is the father of all, can exist on his own or equipped with decorators.
ConcreteComponent: son of component, can do more cool stuff than his old father.
Decorator: sort of the mother of all decorators, it teaches them the ABCs of life without precising how to act.
ConcreteDecorator: the real deal where decorator operations are defined.

Let’s put this in action and see what we get:

Solution with decorator patternSolution with decorator pattern

Explanation:

Our main goal is to treat all pizza objects the same (this is why everything inherits from Pizza class) and provide a mecanism to decorate our objects in a way that makes them different from one another.

The Pizza here is your component, it’s the base class of the object you want to decorate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Pizza
{
public void PreparePizza()
{
}
private void AddSauce()
{
}
public virtual void MakeDough()
{
}
private void PutInOven()
{
}
private void PrepareSauce()
{
}
public virtual string GetIngredients()
{
return "Pizza with ";
}
}

Three classes derive directly from Pizza: the first two (CrustyDoughPizza and ThickDoughPizza) are considered ConcreteComponents since they extend Pizza’s behavior( Exp: creates a different more delicious dough).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class CrustyDoughPizza : Pizza
{
public override void MakeDough()
{
//Make CrustyDough
}
public override string GetIngredients()
{
return "Crusty Dough Pizza with ";
}
}
public class ThickDoughPizza : Pizza
{
public override void MakeDough()
{
//Make thick dough
}
public override string GetIngredients()
{
return "Thick Dough Pizza with ";
}
}

The last third sub class is PizzaIngredient which is the base class of any pizza ingredient since it defines what is expected from an ingredient. In this case, it forces every ingredient to override the behaviour of GetIngredients method of the Pizza class in order to have its own special implementation. Notice also the existence of a pizza field (MyPizza), its use will be covered later.

1
2
3
4
5
public abstract class PizzaIngredient : Pizza
{
public Pizza MyPizza {get; set;}
public override abstract string GetIngredients();
}

Finally, by implementing PizzaIngredient methods, subclasses share the same methods but with custom functionalities therefore they can decorate Pizza objects rendering equally different but without compromising their origin. Hold on a sec, how can they decorate Pizza objects ?

Excellent question, each ingredient must have a constructor which takes a Pizza argument. Decoration occurs when this argument is assigned to the MyPizza property. If we need to decorate an already decorated object, all we need to do is pass in the decorated object as an argument( it’s pizza after all) to the custom constructor of the decorator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Meat : PizzaIngredient
{
public Meat(Pizza pizza)
{
MyPizza = pizza;
}
public override string GetIngredients()
{
return MyPizza.GetIngredients() + " Meat";
}
}
public class Cheese : PizzaIngredient
{
public Cheese(Pizza pizza)
{
MyPizza = pizza;
}
public override string GetIngredients()
{
return MyPizza.GetIngredients() + " Cheese";
}
}
public class Olive : PizzaIngredient
{
public Olive(Pizza pizza)
{
MyPizza = pizza;
}
public override string GetIngredients()
{
return MyPizza.GetIngredients() + " Olive";
}
}

Let’s try to make a CrustyDoughPizza with olive only:

1
2
3
4
5
6
7
8
9
10
CrustyDoughPizza myPizza = new CrustyDoughPizza();
//Decorate the pizza with olive
Olive olivePizza = new Olive(myPizza);
var pizzaIngredients = olivePizza.GetIngredients();
//expected answer = Crusty pizza with olive

How? One word: Recurrence !

When we call GetIngredients of Olive, it will bounce to call GetIngredients of CrustyPizza before it replies back to us just like in the schema below.

RecurrenceRecurrence

Let’s now do a more complicated thing: a ThickDough Cheese and Meat Pizza:

1
2
3
4
5
6
7
8
9
10
ThickDoughPizza myPizza = new ThickDoughPizza();
//Decorate the pizza with Meat
Meat pizzaWithMeat = new Meat(myPizza);
//Decorate the pizza with cheese
Cheese pizzaWithCheese = new Cheese(pizzaWithMeat);
var pizzaIngredients = pizzaWithCheese.GetIngredients();
//expected answer = Crusty pizza with meat cheese

I believe this is a good solution for situation when we don’t have control over the choices of the client. The decorator pattern makes components and decorators behave the same way abstracting differences and eliminating useless conditional tests but you may want to be careful about how you want to adjust your implementation to your case through interfaces and abstract classes