design patterns ·

Decorator

Attaches additional responsibilities to an object dynamically by wrapping it in decorator objects.

easy0.5hgeneraljava
Ask GPTConfidence

Theory

Explanation

Intuition first, formal definition second. Skim the bullets if you already know this; read the prose if you don't.

When you need to add behavior to individual objects (not all instances of a class), wrap them in decorator objects that implement the same interface and delegate to the wrapped object while adding behavior before/after.

Decorators implement the same interface as the component they wrap. Each decorator holds a reference to the component and delegates calls to it, adding behavior before or after the delegation. Decorators can wrap other decorators.

When to use

Java I/O streams, adding logging/caching/auth to services, extending UI components without subclassing, middleware stacks - any time you need to add behavior to individual objects at runtime.

When not to

When you need to add behavior to all instances of a class - subclass or modify the class instead.

Key insights

  • Java's InputStream → BufferedInputStream → DataInputStream is the canonical Decorator example
  • Each decorator adds exactly one responsibility - single responsibility per decorator
  • Decorator and Proxy have similar structures but different intents: Decorator adds behavior, Proxy controls access
  • Recursive wrapping is the mechanism: decorator wraps decorator wraps concrete component