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 hellM×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.