DEV Community

DevCorner2
DevCorner2

Posted on

🎁 Decorator Design Pattern β€” LLD + Java + Real Use Cases

Add behavior to individual objects dynamically without altering their structure β€” a flexible alternative to subclassing.


🧠 What is the Decorator Pattern?

The Decorator Pattern is a structural design pattern that allows you to:

  • Attach additional responsibilities to objects at runtime
  • Wrap objects with other objects that enhance behavior
  • Maintain the original object’s interface

πŸ“¦ Use Cases (Real-World)

Context Example
β˜• Coffee Shop Add milk, sugar, etc. to base beverage dynamically
🧾 Billing System Add discounts, taxes, coupons to final price
πŸ“„ I/O Streams (Java) BufferedReader, DataInputStream, GZIPOutputStream
πŸ›‘οΈ Security Layering Add logging, auth, audit, throttling to requests
πŸ§ͺ Testing Mocks Mock + Spy + Log enhancement

🎯 When to Use It?

βœ… Use when:

  • You need to add features to objects dynamically and transparently
  • You want to avoid subclass explosion
  • You want to compose behavior in a flexible way

🚫 Avoid if:

  • Object configuration is overly complex
  • All variations are known at compile time (prefer inheritance)

🧱 Pattern Structure

Component Role
Component (interface) Declares the core operation
ConcreteComponent The base implementation
Decorator (abstract) Holds a reference to a Component + delegates
ConcreteDecorator Adds extra behavior before/after delegate calls

πŸ“ UML Diagram

+------------------+
|   Component      | <<interface>>
+------------------+
| +operation()     |
+------------------+
        β–²
        |
+-------------------+
| ConcreteComponent |
+-------------------+
| +operation()      |
+-------------------+
        β–²
        |
+-------------------+
|    Decorator      | <<abstract>>
+-------------------+
| - component: Component
| +operation()      |
+-------------------+
        β–²
+--------------------------+
|  ConcreteDecoratorA      |
+--------------------------+
| +operation()             |
+--------------------------+
Enter fullscreen mode Exit fullscreen mode

β˜• Coffee Shop Example in Java

βœ… Beverage.java

public interface Beverage {
    String getDescription();
    double getCost();
}
Enter fullscreen mode Exit fullscreen mode

βœ… Espresso.java (ConcreteComponent)

public class Espresso implements Beverage {
    @Override
    public String getDescription() {
        return "Espresso";
    }

    @Override
    public double getCost() {
        return 100.0;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… BeverageDecorator.java (Abstract Decorator)

public abstract class BeverageDecorator implements Beverage {
    protected Beverage beverage;

    public BeverageDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… MilkDecorator.java (ConcreteDecorator)

public class MilkDecorator extends BeverageDecorator {
    public MilkDecorator(Beverage beverage) {
        super(beverage);
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Milk";
    }

    @Override
    public double getCost() {
        return beverage.getCost() + 20.0;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… SugarDecorator.java

public class SugarDecorator extends BeverageDecorator {
    public SugarDecorator(Beverage beverage) {
        super(beverage);
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Sugar";
    }

    @Override
    public double getCost() {
        return beverage.getCost() + 10.0;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… Client.java

public class DecoratorClient {
    public static void main(String[] args) {
        Beverage espresso = new Espresso();
        System.out.println("Order 1: " + espresso.getDescription() + " | β‚Ή" + espresso.getCost());

        Beverage customCoffee = new MilkDecorator(new SugarDecorator(new Espresso()));
        System.out.println("Order 2: " + customCoffee.getDescription() + " | β‚Ή" + customCoffee.getCost());
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Output

Order 1: Espresso | β‚Ή100.0
Order 2: Espresso, Sugar, Milk | β‚Ή130.0
Enter fullscreen mode Exit fullscreen mode

✨ Benefits

Advantage Explanation
βœ… Flexible composition Add features without changing existing classes
βœ… Open/Closed Principle Extend behavior via composition
βœ… Reuse & layering Chain decorators to build behavior stacks
βœ… No subclass explosion Avoid subclassing for each variation

⚠️ Limitations

  • πŸŽ›οΈ Complex configuration if decorators are stacked dynamically
  • 🧩 Debugging stack layers may be harder than single-class hierarchies

🧾 Summary

Feature Value
Type Structural
Primary Intent Add behavior at runtime
Key Concepts Used Composition, Delegation
Java Real Usage InputStream, Logger, UI themes, Spring AOP

Top comments (0)