Knowledge Guide
HomeOO & Low-Level DesignStructural

Decorator Pattern

The Decorator Pattern is a structural design pattern that enables you to dynamically add new functionalities to objects without changing their structure. This pattern generates a decorator class that wraps the original class and adds functionality, separating the class behaviors and promoting flexible and reusable design.

The Decorator Pattern is a great example of the Open/Closed Principle, which is one of the fundamental principles of object-oriented design. According to this principle, software entities (such as classes, modules, functions, etc.) should be closed for modification but open for extension.

How the Decorator Pattern Applies the Open/Closed Principle:

Real-world Example

Consider a scenario where we have a basic Window class in GUI framework. After some time, we need to change that window and add some borders to it, then add a scroll bar to it. With more advancements, we need to add some themes to that window. Without the Decorator Pattern, this would lead to complex subclassing for every combination (like WindowWithScrollbar, WindowWithBorder, ThemedWindow, etc.).

Decorator Pattern - Problem Illustration
Decorator Pattern - Problem Illustration

But, what can be the solution to this? Decorator patterns can jump in to help us!

With the use of decorator patterns, all these additional features will become decorators like ScrollBarDecorator, BorderDecorator, and ThemeDecorator, extending the Window class. We can add these decorators to the Window class dynamically.

Decorator Pattern - Solution Illustration
Decorator Pattern - Solution Illustration

Structure of Decorator Pattern

The main components of the Decorator Pattern include:

Decorator Pattern - Class Diagram
Decorator Pattern - Class Diagram

Implementation of Decorator Pattern

Consider a Pizza creation application in which you can create pizzas with multiple toppings. Each pizza will have its own flavor and cost. This application can be implemented using the Decorator Pattern.

Didn't get this point? Don't worry! The pseudocode will explain you.

INTERFACE Pizza METHOD getCost() METHOD getDescription() CLASS PlainPizza IMPLEMENTS Pizza METHOD getCost() RETURN base price of pizza METHOD getDescription() RETURN "Plain Pizza" CLASS ToppingDecorator IMPLEMENTS Pizza PROTECTED component: Pizza CONSTRUCTOR ToppingDecorator(newComponent: Pizza) component = newComponent METHOD getCost() RETURN component.getCost() METHOD getDescription() RETURN component.getDescription() CLASS CheeseDecorator EXTENDS ToppingDecorator METHOD getCost() RETURN component.getCost() + cost of cheese METHOD getDescription() RETURN component.getDescription() + ", Cheese" CLASS PepperoniDecorator EXTENDS ToppingDecorator METHOD getCost() RETURN component.getCost() + cost of pepperoni METHOD getDescription() RETURN component.getDescription() + ", Pepperoni"

With the help of this pattern, you can dynamically build a pizza with different toppings that can be added one at a time without having to make a new subclass for every potential combination.

Implementation

java
interface Pizza {
  double getCost();
  String getDescription();
}

class PlainPizza implements Pizza {

  public double getCost() {
    return 10.0;
  }

  public String getDescription() {
    return "Plain Pizza";
  }
}

abstract class ToppingDecorator implements Pizza {

  protected Pizza pizza;

  public ToppingDecorator(Pizza newPizza) {
    pizza = newPizza;
  }

  public double getCost() {
    return pizza.getCost();
  }

  public String getDescription() {
    return pizza.getDescription();
  }
}

class CheeseDecorator extends ToppingDecorator {

  public CheeseDecorator(Pizza newPizza) {
    super(newPizza);
  }

  public double getCost() {
    return pizza.getCost() + 2.5;
  }

  public String getDescription() {
    return pizza.getDescription() + ", Cheese";
  }
}

class PepperoniDecorator extends ToppingDecorator {

  public PepperoniDecorator(Pizza newPizza) {
    super(newPizza);
  }

  public double getCost() {
    return pizza.getCost() + 3.0;
  }

  public String getDescription() {
    return pizza.getDescription() + ", Pepperoni";
  }
}

// Usage:
public class Solution {

  public static void main(String[] args) {
    Pizza pizza = new PlainPizza();
    pizza = new CheeseDecorator(pizza);
    pizza = new PepperoniDecorator(pizza);

    System.out.println("Cost: " + pizza.getCost());
    System.out.println("Description: " + pizza.getDescription());
  }
}

Applications of Decorator Pattern

Pros and Cons

Here's a table summarizing the pros and cons of the Decorator Pattern:

ProsCons
Enhanced Flexibility: It allows dynamic extension of functionality without disturbing the underlying object.Complexity: Can introduce a significant amount of small classes, which can complicate the code and increase complexity.
Avoids Class Proliferation: Avoids creating too many classes for every new functionality.Indirection: Adds layers of abstraction which can complicate debugging and understanding the code.
Extensibility: Complies with the Open/Closed Principle, making it easy to introduce new features without affecting existing code.Overuse: Improper use can lead to systems with lots of tiny objects that could have been a simpler design.
Runtime Changes: Alterations can be done at runtime which increases the flexibility of objects used.Performance Issues: Each decorator adds a level of indirection that can impact runtime performance.
Separation of Concerns: Provides better separation between the existing code and new functionalities.Design Complexity: Proper design requires a deep understanding of the goal and careful planning, as misuse can lead to a confusing system architecture.

This table presents a balanced view of the Decorator Pattern's capabilities in extending functionality while highlighting potential challenges in its application.

🤖 Don't fully get this? Learn it with Claude

Stuck on Decorator Pattern? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Decorator Pattern** (OO & Low-Level Design) and want to truly understand it. Explain Decorator Pattern from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Decorator Pattern** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Decorator Pattern** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Decorator Pattern** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes