The Decorator pattern adds behavior to an object dynamically by wrapping it in another object with the same interface. The wrapper forwards the call to the wrapped object and does something before or after. Unlike inheritance, decorators can be stacked and chosen at runtime.

Why not subclasses?

A coffee can get any combination of add-ons. With inheritance each combination is a class: two bases and three add-ons already need 16, and every new add-on doubles the count.

python
from itertools import combinations

bases = ["espresso", "tea"]
addons = ["milk", "sugar", "cream"]

combos = [(base, extra)
          for base in bases
          for r in range(len(addons) + 1)
          for extra in combinations(addons, r)]
print(len(combos))              # subclasses needed with inheritance
print(combos[:3])
text
16
[('espresso', ()), ('espresso', ('milk',)), ('espresso', ('sugar',))]

Structure

Espresso, Milk and Sugar implement Beverage; the decorators hold an inner Beverage
Espresso, Milk and Sugar implement Beverage; the decorators hold an inner Beverage

A decorator is a Beverage (implements the interface) and has a Beverage (holds inner). Each method delegates to inner and adds its part, so any number of decorators can be nested.

python
class Espresso:
    def description(self):
        return "espresso"

    def cost(self):
        return 200