Skip to content

Design Pattern: Decorator (Structural)

Add behaviour at runtime without subclassing

Builds on Composition vs Inheritance and OCP - The Open/Closed Principle

Stage 3core2 min read

1. Introduction

Structural design patterns are about how classes and objects are put together into larger structures. The Decorator Pattern is one of them. It adds new behavior to an object while the program runs. Inheritance cannot do this, because it is fixed when the code is written.


2. The Decorator Pattern

The Decorator Pattern adds behavior to one object at runtime. Other objects of the same class are not changed. It "wraps" the object inside a decorator object. The decorator adds the new behavior and has the same interface (the same methods) as the object it wraps, so callers use it the same way.

Real-Life Analogy: The Coffee Shop

Think of ordering a coffee:

  1. You start with a Simple Coffee.
  2. You can add Milk, Sugar, or Whipped Cream.
  3. You do not need a new "CoffeeWithMilkAndSugar" class. You "wrap" the base coffee with the additions you want.

3. Class Diagram

In the diagram, PizzaDecorator sits in the middle. It is a Pizza and it also holds a Pizza. This lets a topping such as ExtraCheese wrap a MargheritaPizza, a PlainPizza, or another topping.

Loading diagram…

4. Problem & Solution Summary

The Problem: Class Explosion

Say you use inheritance for every mix of toppings. You get far too many classes (CheesePizza, OlivePizza, CheeseAndOlivePizza, and so on). This is called Class Explosion.

The Solution: Composition over Inheritance

The Decorator Pattern uses layers instead. Each decorator is like gift wrap around the pizza. At runtime you can stack as many layers as you like. Each layer adds its own description and cost.


5. Pros and Cons

ProsCons
Open/Closed Principle: You can add new toppings (decorators) without editing existing pizza classes.Many Small Classes: Each new feature needs its own decorator class, which can fill up the project.
Runtime Flexibility: Behaviors can be added dynamically while the app is running.Complex Debugging: With many layers, stack traces (the list of calls shown in an error) are harder to follow.
Avoids Subclass Explosion: No need for $2^N$ classes to cover every combination.Learning Curve: You must understand the "chaining": each decorator calls the one inside it.

6. Real-World Use Cases

  1. Food Delivery Apps (Swiggy/Zomato): Dynamically adding toppings, sauces, or sides to a base food item.
  2. Word Processors (Google Docs): Applying text styles like Bold, Italic, or Underline in any combination.
  3. Java I/O Streams: Using BufferedReader(new FileReader("file.txt")) is a classic implementation of the Decorator Pattern in the Java standard library.

Key Takeaway: The Call Stack Analogy

The Decorator Pattern works like a Call Stack. Call getCost() on the outermost decorator. It calls getCost() on the one inside it, and so on, until the base pizza answers. The values then come back up, and each layer adds its own cost.

In this topic

Done with this topic?

How well do you know it?

PreviousDesign Pattern: Adapter (Structural)