Skip to main content

Sign in to CleanKata

Track your progress, earn XP, and unlock every lesson.

By signing in you agree to our Terms of Use and Privacy Policy.

Design Patterns80 XP9 min

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