Structural

Decorator

Attaches additional responsibilities to objects dynamically.

HTTP middlewareStream wrappersLogging decorators

Understanding Decorator

The Decorator pattern wraps an object with additional behavior without modifying its original code. Each decorator implements the same interface as the object it wraps, so decorators can be stacked — adding logging, then authentication, then caching — all transparently. In Go, this pattern is the foundation of http.Handler middleware chains, where each middleware wraps the next handler, adding cross-cutting concerns like CORS, rate limiting, or request tracing.

Key Concepts

  • Same interface — both the base component and decorators implement the same interface, making them interchangeable
  • Wrapping composition — each decorator holds a reference to the next component in the chain and delegates to it
  • Stackable — decorators can be combined in any order and quantity, with behavior flowing through the entire chain
  • Open/Closed principle — extend behavior by adding new decorators, without modifying existing component code

When to Use

✅ Use when
  • • Adding behavior to individual objects without affecting others
  • • Building middleware pipelines (HTTP, gRPC, message processing)
  • • You need to combine behaviors in different ways at runtime
  • • Subclassing would result in an explosion of classes for each combination
⚠️ Avoid when
  • • The order of decorators matters and is hard to get right
  • • Deeply nested decorators become hard to debug and trace
  • • A simple function composition would be clearer in Go

Structure

<<Component Interface>>
↓ implements
Base
Decorator A
wraps ↓
Decorator B
wraps ↓
Base

How It Works

BaseHandler
Handle()
1

Base Component

Start with a base component that has core functionality.

1 / 4

Basic Implementation

Coffee shop with customizable add-ons:

main.go
Loading editor...

Real-World Example: HTTP Middleware

Request handling with authentication and logging decorators:

main.go
Loading editor...