🔍 What is the Decorator Pattern?

The Decorator Pattern is a structural design pattern that allows behavior to be added to individual objects, either statically or dynamically, without altering the structure of the original class.


✅ When Should You Use It?

  • When you want to add responsibilities to objects dynamically at runtime.
  • When subclassing would lead to too many classes.
  • To follow Open-Closed Principle: classes should be open for extension but closed for modification.

🧠 Real-World Analogy

Imagine you order a coffee ☕. You start with a base coffee, and then decorate it with milk, sugar, mocha, or whipped cream — all dynamically layered, without modifying the base coffee class.


🧱 Structure

+-------------------+
            |   Component       |  <-- Interface
            +-------------------+
                     ^
                     |
        +------------------------+
        |     ConcreteComponent  |  <-- Base Implementation
        +------------------------+
                     ^
                     |
        +------------------------+
        |      Decorator         |  <-- Abstract Wrapper
        +------------------------+
                     ^
           ------------------------
           |         |           |
    MilkDecorator  SugarDecorator  etc. <-- Concrete Decorators

☕ Example: Coffee Shop


✅ 1. Component Interface

public interface Coffee {
    String getDescription();
    double cost();
}

✅ 2. ConcreteComponent

public class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "Simple Coffee";
    }

    @Override
    public double cost() {
        return 5.0;
    }
}

✅ 3. Abstract Decorator

public abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

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

    public double cost() {
        return decoratedCoffee.cost();
    }
}

✅ 4. Concrete Decorators

public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return super.getDescription() + ", Milk";
    }

    public double cost() {
        return super.cost() + 1.5;
    }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return super.getDescription() + ", Sugar";
    }

    public double cost() {
        return super.cost() + 0.5;
    }
}

public class MochaDecorator extends CoffeeDecorator {
    public MochaDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return super.getDescription() + ", Mocha";
    }

    public double cost() {
        return super.cost() + 2.0;
    }
}

💻 Client Code

public class DecoratorDemo {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.getDescription() + " $" + coffee.cost());

        coffee = new MilkDecorator(coffee);
        coffee = new SugarDecorator(coffee);
        coffee = new MochaDecorator(coffee);

        System.out.println(coffee.getDescription() + " $" + coffee.cost());
    }
}

🧪 Output

Simple Coffee $5.0
Simple Coffee, Milk, Sugar, Mocha $9.0

🎯 Benefits

✅ Follows Open-Closed Principle

✅ Runtime behavior change

✅ Composable and reusable wrappers

✅ Cleaner than multiple subclasses


🧑‍🏫 Key Takeaways

  • The Decorator Pattern is perfect when you want to extend behavior without modifying classes.
  • It helps you avoid creating too many subclasses.
  • You can keep adding layers of decorators to wrap original functionality.

🧩 Java Libraries Using Decorator

  • BufferedReader, BufferedInputStream, PrintWriter in java.io 🎯
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

🚀 Up Next for Day 5: Want to go with Strategy, Adapter, State, or Chain of Responsibility?

Let me know your pick and I’ll deliver another deep-dive, code-rich, real-world blog for the next one!