Structural patterns
Compose classes and objects into larger structures while keeping those structures flexible and efficient.
Adapter
The Adapter converts the interface of an existing class into another interface that a client expects. It lets classes work together that couldn't otherwise because of incompatible interfaces — without modifying either.
Real-world analogy: a power adapter. Your laptop expects USB-C; the wall outlet provides AC. The adapter bridges the gap. In code, you wrap the adaptee in a class that implements the target interface and translates calls.
When should you reach for the Adapter pattern?
Decorator
The Decorator wraps an object to add new behavior at runtime, transparently. Unlike inheritance (which is static and affects all instances), decorators compose dynamically — you can stack them in any combination.
The key constraint: the decorator implements the same interface as the component it wraps. Clients can't tell whether they're talking to the original or a decorated version. This enables open-ended extension without modifying existing classes.
What advantage does Decorator have over subclassing for adding behavior?
Composite
The Composite lets you treat individual objects and groups of objects uniformly. Both leaf nodes and composite (container) nodes implement the same interface, so client code doesn't need to distinguish between them.
Classic examples: file systems (files and directories), UI component trees (buttons and panels), organizational charts (employees and departments). Any tree-like structure where operations apply recursively benefits from Composite.
What is the defining characteristic of the Composite pattern?
Facade
The Facade provides a unified, simplified interface to a complex subsystem. It doesn't replace the subsystem's classes — it sits in front of them, coordinating calls and hiding internal complexity from clients.
Unlike Adapter (which changes an interface to match what a client expects), Facade creates a new, simpler interface on top of existing complexity. The subsystem remains fully accessible for advanced use cases.
Without Facade
- Client knowledge
- Must know all subsystem classes
- Coupling
- Tightly coupled to internals
- Change impact
- Subsystem changes ripple to clients
With Facade
- Client knowledge
- Knows only the facade
- Coupling
- Loosely coupled via stable interface
- Change impact
- Facade absorbs subsystem changes
How does Facade differ from Adapter?