← Home
🏗Crack System Design with DSA AnimatorSystem DesignNEW
🏗 System Design›Structural Patterns

🎁Decorator Pattern

Attach additional responsibilities to an object dynamically — transparent wrappers.

📌 Key IdeaImplement the same interface as the wrapped object; delegate core calls inward; add behaviour before/after. Avoids subclass combinatorics (MilkSugarVanillaLatte). JDK poster child: `InputStream` decorators.
🖼

Visual

🎁 Stack behaviours
  Coffee c = new SugarDecorator(
               new MilkDecorator(new SimpleCoffee()));
  // java.io: new BufferedInputStream(
  //              new FileInputStream(path))

Each decorator holds a reference to Component — nesting = stacking features.

✅

When to Use

  • You need optional cross-cutting layers: compression, encryption, logging, timing.
  • Subclass explosion if you modeled every combination explicitly.
  • Behaviour must be added at runtime (configuration, feature flags).
🚫

When NOT to Use

  • Wrapping fixes wrong interface — that is Adapter.
  • Object identity matters (==) — decorators change wrapper identity unless handled.
🚨

Anti-Pattern (What NOT to Do)

Subclass explosionBadjava
class MilkSugarCoffee extends Coffee {}
class SugarMilkCoffee extends Coffee {} // combinatorial hell
M×N flavours → M×N classes.
✅

The Right Way

Composable decoratorsGoodjava
interface Coffee { double cost(); }
class MilkDecorator implements Coffee {
    private final Coffee inner;
    public double cost() { return inner.cost() + 0.5; }
}
Order of wrapping can matter for some behaviours.
⚖️

Pros & Cons

👍 Pros
  • Follows Open/Closed — extend behaviour without editing originals.
  • Composable — mix decorators in different orders (when safe).
👎 Cons
  • Small objects everywhere — debugging stack of wrappers.
  • Order-dependent behaviour can surprise readers.
🔀

Common Confusions Cleared Up

Decorator vs Subclassing

Subclassing is static — compile-time specialisation. Decorator composes behaviour flexibly at runtime by stacking wrappers.

Decorator vs Proxy

Proxy usually controls access (lazy load, security, remote). Decorator adds responsibilities. Same structure — different intent.

🎤

Interview Q&A

🔮

Likely Follow-up Questions

  • When does decorator order matter (e.g. caching before vs after validation)?
🧾

Quick Cheat Sheet

IntentAdd duties dynamically; same interface.
JDKCollections synchronizedX, IO streams.
vs ProxyEnhance vs control access.
🔗

Related Topics