Open In App
Related Articles

Decorator Pattern | Set 1 (Background)

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

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.

pizza1 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 1 Create a new subclass for every topping with a pizza. The class diagram would look like:pizza2

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:pizza3

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  problem.

References: Head First Design Patterns( Book).


Last Updated : 31 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads