Decorator: Adding Superpowers
Add behavior to objects dynamically by wrapping them — compose capabilities instead of creating an explosion of subclasses.
Why this matters
Inheritance is the obvious solution when you need to add behavior — until you need combinations. A coffee shop with Espresso, Milk, Sugar, and Caramel can produce 16 combinations. Subclassing gives you 16 classes. Adding Vanilla makes it 32. The Decorator pattern escapes this explosion: each wrapper implements the same interface and holds a reference to another instance of that interface. You stack decorators like LEGO bricks — unlimited combinations from a small set of parts.
In the wild
Python's own @functools.wraps, logging handlers, and middleware stacks all use the Decorator pattern. Django and FastAPI middleware layers are decorators. The pattern is also the foundation of Python's @decorator syntax, though function decorators are a simpler variant that wraps callables rather than objects.
💡Key takeaway
If you're creating subclasses for every combination of features, use Decorator. Prefer composition over inheritance — a handful of decorators unlocks more combinations than any class hierarchy.
🔧 Some exercises may still have errors. If something seems wrong, use the Feedback button (bottom-right of the page) to report it — it helps us fix it fast.
Hint: If you're creating subclasses for every combination of features, use Decorator. Prefer composition over inheritance.
✗ Your version