Design Pattern : Decorator Pattern
` A structural design pattern, that attaches additional responsibilities to an an object dynamically`
The Decorator pattern falls under the category of Structural Design patterns. These patterns talk about how to assemble objects and classes into larger structures while keeping these structures flexible and efficient.
Scenario
We are working for a ‘wizarding’ client Madam Rosmerta (All the Harry Potter fans, you are in for a ride to The Three Broomsticks in Hogsmeade)for her The Three Broomsticks Inn. It is famous for the beverages that is sold. As her business is picking up quickly , she wants The Three Broomsticks Inn to have an ordering system in place.
( I understand what you are thinking, “Why would Madam Rosmerta require the help of technology , when she can just wave her wand and caste some spell ?”, The answer is, just to understand Decorator pattern 😛). Let’s take a look at the initial design .
In addition to this, customers can request for additional condiments like : Ice, creame , soda and much more. These condiments are also charged , so Three Broomsticks require this in their ordering system.
What will happen if Madam Rosmerta decides to introduce new menu ? This will lead to a ‘class explosion’ and a maintenance nightmare.
Hmm…… inheritance doesn’t help us much in this case.
We want our class to easily extend to incorporate new behaviour. How about adding a boolean variable to store each condiments ?
For two condiment classes, this seems okay. But what if we have many condiments? Think about how we need to modify the cost() ?
‘ Classes should be open for extension, but closed for modification.’
Our goal is to allow classes to be easily extended to incorporate new behaviour without modifying existing code. Our approach to implementing beverages and condiments using inheritance has not worked out well. We also arrived at rigid designs.
So how we arrive at a good design ?
We’ll start with a beverage and “decorate” it with the condiments at runtime.
So when anyone in Hogsmeade’s Three Broomsticks order CherrySyrup with Ice in, we’ll start with
1. Create a CherrySyrup object.
2. Decorate it with Ice object
3. Call the cost() method and rely on delegation to add up the cost() of condiments.
I know what you are thinking , “ How are we going to decorate and how are we going to delegate ?”
Constructing a Decorator :
1. Let’s first start with a CherrySyrup object. It inherits from Beverage and has cost() that computes the cost of the drink.
2. Now the customer wants Ice with it. We’ll create an Ice object which is of the type Beverage. This object is a decorator, we will wrap it around CherrySyrup. So CherrySyrup has cost() method too and through polymorphism , we can treat any Beverage wrapped in Ice as Beverage too.
To calculate the total cost , we call the cost() of outermost decorator Ice, and Ice is going to delegate computing the cost to the objects it decorates.
With all the points, let’s see how this really works by looking at the decorator pattern.
Now that we have understood the decorator pattern, let’s code the beverage and its subclasses.
Serving some CherrySyrup!
Now that we have all the code in place, let’s code some test class to see our ThreeBroomSticks ordering system in action ;)
And here’s the output .
Madam Rosmerta is very happy with her new ordering system for ThreeBroomSticks and I hope you, are happy now that you understood Decorator pattern. 🙂
Thanks for reading !
I also have other blogs on design pattern check out the link.
1. Strategy Design Pattern
2. Observer Design Pattern