Skip to main content

What It Is

The Decorator pattern adds behavior to an object by wrapping it in another object with the same interface. Each wrapper does its extra bit and passes the call on to what it wraps.

Because wrapper and wrapped share the interface, wrappers stack in any combination — like layers of clothing.


Example: Wrapping a Notifier

The plain notifier sends an email. One wrapper adds logging before the send; another adds an SMS after it. The caller still sees a plain Notifier.

Layers around a core

WithLog{WithSMS{EmailNotifier{}}} reads inside-out: email at the core, SMS around it, logging outermost. Any layer can be added, removed, or reordered without touching the others.

Prompt
Write a Go program with the Decorator pattern: a Notifier interface (Send method), a plain EmailNotifier, a WithLog decorator that prints a log line before passing the call on, and a WithSMS decorator that also sends an SMS after. Stack the decorators around the email notifier and send one message.
Output: Go program and captured output
Layers around a core

When to Use It

Use it to add optional, combinable behavior — logging, caching, retries, metrics — around a core you do not want to modify. Middleware in web servers is exactly this pattern.

Skip it when the behavior is not optional and not combinable — then it belongs inside the type itself, where it is easier to find.


Pros and Cons

Pros: behavior added without touching the core type; layers combine freely; each layer is small and testable alone.

Cons: a deep stack of wrappers is hard to debug — the call travels far before doing anything; construction lines get long.