Behavioral patterns
Define how objects communicate, distribute responsibilities, and encapsulate algorithms.
Observer
The Observer establishes a one-to-many dependency: when the subject changes state, all registered observers are notified and updated automatically. The subject doesn't know the concrete types of its observers — only that they implement a notification interface.
This is the foundation of event-driven architectures, reactive programming, and pub/sub systems. DOM event listeners, RxJS observables, Redux store subscriptions, and Vue's reactivity system are all Observer variants.
What problem does the Observer pattern solve?
Strategy
The Strategy extracts varying algorithms into separate classes that share a common interface. The context holds a reference to a strategy and delegates to it — swapping strategies changes behavior without modifying the context.
This replaces conditional logic (if/else, switch) with polymorphism. Instead of a giant function with branches for each algorithm, each branch becomes its own class implementing the strategy interface.
What does the Strategy pattern replace?
Command
The Command encapsulates a request as an object — bundling the action, its parameters, and the receiver into a single callable entity. This decouples the invoker (who triggers the action) from the receiver (who performs it).
Because commands are objects, you can queue them, log them, serialize them, support undo/redo, or schedule them for later execution. Text editors, task schedulers, and transactional systems rely heavily on this pattern.
What capability does Command unlock that direct method calls cannot?
Iterator
The Iterator provides a way to traverse a collection without exposing its internal structure (array, linked list, tree, hash map). The client gets a uniform traversal interface regardless of how the collection stores its elements.
Modern languages have largely absorbed this pattern into the language itself: JavaScript's `for...of`, Python's `iter()`/`next()`, Java's `Iterable`, C#'s `IEnumerable`. You rarely implement Iterator from scratch anymore — but understanding it explains why these constructs work.
Why has the Iterator pattern been largely absorbed into modern programming languages?