Decorator Pattern | Set 1 (Background) - GeeksforGeeks

15 Feb, 2018
To understand decorator pattern let us consider a scenario inspired from the book “Head First Design Pattern”.  Suppose we are building an application for a pizza store and we need to model their pizza classes. Assume they offer four types of pizzas namely Peppy Paneer, Farmhouse, Margherita  and Chicken Fiesta. Initially we just use inheritance and abstract out the common functionality in a Pizza class.
Each pizza has different cost. We have overridden the getCost() in the subclasses to find the appropriate cost. Now suppose a new requirement, in addition to a pizza, customer can also ask for several toppings such as Fresh Tomato, Paneer, Jalapeno, Capsicum, Barbeque, etc. Let us think about for sometime that how do we accommodate changes in the above classes so that customer can choose pizza with toppings and we get the total cost of pizza and toppings the customer chooses.
Let us look at various options.
Option 1Create a new subclass for every topping with a pizza. The class diagram would look like:
This looks very complex. There are way too many classes and is a maintenance nightmare. Also if we want to add a new topping or pizza we have to add so many classes. This is obviously very bad design.
 
Option 2:Let’s add instance variables to pizza base class to represent whether or not each pizza has a topping. The class diagram would look like:
The getCost() of superclass calculates the costs for all the toppings while the one in the subclass adds the cost of that specific pizza.
 
// Sample getCost() in super class
public int getCost()
{
    int totalToppingsCost = 0;
    if (hasJalapeno() )
        totalToppingsCost += jalapenoCost;
    if (hasCapsicum() )
        totalToppingsCost += capsicumCost;

    // similarly for other toppings
    return totalToppingsCost;
}

// Sample getCost() in subclass
public int getCost()
{
    // 100 for Margherita and super.getCost()
    // for toppings.
    return super.getCost() + 100;
}
This design looks good at first but lets take a look at the problems associated with it.
Price changes in toppings will lead to alteration in the existing code.
New toppings will force us to add new methods and alter getCost() method in superclass.
For some pizzas, some toppings may not be appropriate yet the subclass inherits them.
What if customer wants double capsicum or double cheeseburst?
In short our design violates one of the most popular design principle – The Open-Closed Principle which states that classes should be open for extension and closed for modification.
In the next set, we will be introducing Decorator Pattern and apply it to above above problem.
References: Head First Design Patterns( Book).
This article is contributed by Sulabh Kumar. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Design Pattern
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Unified Modeling Language (UML) | An Introduction
Unified Modeling Language (UML) | State Diagrams
Composite Design Pattern
Observer Pattern | Set 1 (Introduction)
Abstract Factory Pattern
Monolithic vs Microservices architecture
Prototype Design Pattern
Chain of Responsibility Design Pattern
Unified Modeling Language (UML) | Class Diagrams
Singleton Design Pattern | Introduction