Lesson 16 of 17 2 min

LLD Lesson: The Decorator Pattern

Learn how to add responsibilities to objects dynamically without inheritance. Perfect for pizza toppings, coffee shops, and notification decorators.

1. The Problem: Class Explosion

Imagine a Coffee shop. You have a BaseCoffee class. You want to add Milk, Sugar, Mocha, and Whip.

  • If you use inheritance, you need a class for every combination: CoffeeWithMilk, CoffeeWithMilkAndSugar, etc.
  • This leads to hundreds of classes that are impossible to maintain.

2. The Solution: Decorator Pattern

A decorator "wraps" the original object. It has the same interface as the object it's decorating.

The Implementation

public abstract class CoffeeDecorator implements Coffee {
    protected Coffee baseCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.baseCoffee = coffee;
    }
}

public class MilkDecorator extends CoffeeDecorator {
    public double getCost() {
        return baseCoffee.getCost() + 0.50;
    }
}

3. Real-world Intuition: The Winter Clothing

You are the "Base Object."

  1. You put on a Shirt (Decorator 1).
  2. You put on a Sweater (Decorator 2) over the shirt.
  3. You put on a Jacket (Decorator 3) over the sweater. Each layer adds "Warmth" (Behavior) without changing who you are.

4. Interview Discussion

  • Trade-offs: Decorators can make it hard to identify the original object (it's buried under layers). They also result in many small objects.
  • Java I/O Example: new BufferedReader(new FileReader("file.txt")) is the most famous use of the Decorator pattern in the Java JDK.

Final Takeaway

Use the Decorator pattern when you need to add or remove behavior at Runtime.

Want to track your progress?

Sign in to save your progress, track completed lessons, and pick up where you left off.