Skip to main content
Design Patterns 80 XP · 9 min

Decorator: Adding Superpowers

Add behavior to objects dynamically by wrapping them — compose capabilities instead of creating an explosion of subclasses.

Showing
Ad (728×90)

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.

The problem

Bad

The solution

Good

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.

Done with this lesson?

Mark it complete to earn XP and track your progress.