Decorator Design Pattern

mina medhat
4 min readDec 6, 2018

--

The story of my Coffee Shop:

there is a well known Coffee shop Called GalaxyBucks, it has an traditional menu but in the last period the marketer found that the number of peoples that visit the coffee shop is decreased.
So he decided to solve this Problem, and make a lot of varieties like milk, mocha, chocolates, soy …etc to the menu.

current implementation:

he open the current implementation of the menu and found this implementation:

menu implementation

Coffee : is an abstract class.
and the menu has 4 items of coffee : Americano , Espresso ,Cappuccino , deCaf.

So he added all the new options as a subclass under Coffee SuperClass So the result is:

after he finished the implementation he felt that there is something wrong

the problems in this implementation:

  • this is an overcrowded and condenser implementation.
  • if you want to add a new category or new coffee type you will create it’s own Class and implement it.
  • what happens if the milk price is changed?! you will change in all cost method in all coffee classes. (open for modification)

Let’s see how the design pattern will solve this problems :

First we should be familiar with a very important Design Principle in the software it is the second one in SOLID principle for Uncle Bob

Open/Close Principle: classes should be open for extension, but closed for modification

Second we will define the Decorator pattern , it is from the structure design pattern

Decorator Design pattern: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

which means that you can attach a specific function or an additional behavior to your object lets apply this in our coffeeshop
our UseCase: we want to calculate the cost of an americano Coffee cup with double Mocha, milk and Chocolate.

How will we do that ?
- take the Americano coffee subclass.
- decorate it with mocha and then decorate it with mocha again.
- decorate it with milk and then decorate it with chocolate.
- call cost() of this component to calculate it with adding the costs of other decoration items.

The Core Implementation of this design pattern:

Our coffee-shop implementation:

- component can be used by each own or wrapped by a decoration.
- ConcreteComponent: it is the subclass that can be decorated by any decoration item.
- Decorator implements same interface or abstract class as the component it is going to decorate.
- each decorator HAS-A (wraps) a component, which means that the decorator hold a reference variable of the component that is going to decorate it.
- note: we but the wrappedObject: coffee in each subClass Of the decorator just for simplification the implementation in the code below

now note the implementation of the cost method in each class in our use-case “american Coffee cup with double Mocha, mild and Chocolate.”

For American Coffee:

Note: coffee is an abstract class with abstract method float Cost();

For Mocha,Milk and Chocolate Decorator implementation:

Note: CoffeeDecorator is an abstract class extends Coffee abstract class.
Note: if abstract Class extends other abstract class it is option to overwrite the abstract methods of the parent Class but in all cases there will not be a compilation error.

Note: we met the SOLID Principles by this implementation into:
1- we didn’t modify the coffee parent class.
2- it is simple to add new decorator like (soy) or add a new type of coffee by extending the parents classes and without modifying them so it is open for extension, but closed for modification.

Now our Main implementation for our use-case is :

So now you will get this check 0.o:
“your check for americano coffee with double mocha &milk& choclate is 2.0 $”

Enjoy and Bon appétit ;)

References:
SourceMaker & head first design pattern.

--

--