Structural 2 — Decorator
In one line
Wrap an object to add behavior at runtime, stackable without touching the original class.
Think of it like this
Coffee toppings. Start with plain coffee, add milk, then caramel, then whipped cream. Each topping wraps the coffee and adds a bit to the price, and you can stack them in any order.
Key ideas
- 01
Solves: adding responsibilities (logging, compression, rate-limiting, retries) without a class explosion.
- 02
Stack of wrappers: BufferedInputStream → Java's classic example.
- 03
Same interface on the wrapper — clients don't know they're decorated.
- 04
Interview favorite: coffee/beverage pricing, or decorating a rate limiter around a cache.
Java / Spring map
- →
java.io (BufferedInputStream wraps FileInputStream); Spring's @Transactional proxies are decorators.
Code & diagrams
Rate limiter wrapped around a ticket repository.
public interface TicketRepository { Ticket findBy(String id); }
public class DbTicketRepository implements TicketRepository {
public Ticket findBy(String id) { return new Ticket(id); } /* real DB call */
}
// decorator #1: adds rate limiting without editing DbTicketRepository
public class RateLimitedTicketRepository implements TicketRepository {
private final TicketRepository delegate;
private final RateLimiter limiter;
public RateLimitedTicketRepository(TicketRepository d, RateLimiter l) {
this.delegate = d; this.limiter = l;
}
public Ticket findBy(String id) {
if (!limiter.allow("read-ticket")) throw new TooManyRequests();
return delegate.findBy(id);
}
}
// decorator #2: adds caching. Stack them freely:
// new CachedTicketRepository(new RateLimitedTicketRepository(new DbTicketRepository(), rl), cache);Explain without notes
How is this different from inheritance? What does a stack of decorators look like?
Practice
Add Logging + Metrics decorators to NotificationSender and stack all three.
Trade-offs
- ↔
Decorators blur identity (equals/hashCode, instanceof) and stack order matters: cache-then-rate-limit and rate-limit-then-cache behave differently.
Completion checklist
I can build a stack of decorators and explain why their order changes behaviour.