Objects need to collaborate to accomplish tasks. Behavioral patterns define clear communication protocols, making interactions flexible and maintainable.
Lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.).
A collection is just a container for a group of objects. Most common collections are based on lists lists, but often they are based on stacks, trees, graphs and other complex data structures. But no matter how a collection is structured, it must provide some way of to go through each element of the collection. It’s an easy job if the collection is based on a list (loop over all the elements); but for example it is not on a tree (you might need depth-first traversal once, then breadth-first traversal another time, etc.).
Adding more and more traversal algorithms to the collection gradually blurs its primary responsibility, which is efficient data storage. Additionally, some algorithms might be tailored for a specific application, so including them into a generic collection class would be weird. On the other hand, the client code that’s supposed to work with various collections may not even care how they store their elements. However, since collections all provide different ways of accessing their elements, you have no option other than to couple your code to the specific collection classes.
The main idea of the Iterator pattern is to extract the traversal behavior of a collection into a separate object called an iterator.
In addition to implementing the algorithm itself, an iterator object encapsulates all of the traversal details, such as the current position and how many elements are left till the end. Because of this, several iterators can go through the same collection at the same time, independently of each other.
Usually, iterators provide one primary method for fetching elements of the collection. The client can keep running this method until it doesn’t return anything, which means that the iterator has traversed all of the elements.
All iterators must implement the same interface. This makes the client code compatible with any collection type or any traversal algorithm as long as there’s a proper iterator. If you need a special way to traverse a collection, you just create a new iterator class, without having to change the collection or the client.
Example:

This way, the iterator pattern lets you traverse different data structure, even if some of them are unknown beforehand; also complexity is hidden from the client.

Defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure.
Several classes may implement the same overall algorithm but differ in a few details. For example, different document importers may all open a file, parse content, extract data, validate it, and close resources, while each file format needs different parsing logic.
If every class implements the whole algorithm on its own, common steps get duplicated. If the algorithm changes, the same fix has to be repeated in many places.
Template Method puts the fixed algorithm structure in a base class. The base class defines a template method that calls a sequence of steps in a specific order.
Some steps are implemented directly in the base class. Other steps are abstract or hook methods that subclasses can override. This lets subclasses customize parts of the algorithm without changing the algorithm’s overall order.
In short: use Template Method when the workflow is stable, but some steps vary between subclasses.
The pattern typically has these roles:
Abstract Class Defines the template method and declares the steps that subclasses may implement or override.
Concrete Classes Implement the variable steps while keeping the algorithm structure defined by the base class.
Hooks Optional methods with default behavior that subclasses may override only when needed.
Lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.
Some requests may need to pass through several possible processors before they are handled. For example, an app may check authentication, permissions, rate limits, cache, and validation before executing a request.
If the sender knows all possible handlers, it becomes tightly coupled to them. If the checks are hardcoded in one large method, adding or reordering behavior becomes risky and messy.
Chain of Responsibility turns each check or processing step into a handler object. Handlers share a common interface and can be linked into a chain.
When a request arrives, a handler can process it, stop the chain, or pass it to the next handler. The sender only knows the first handler in the chain, so handlers can be rearranged, replaced, or extended without changing sender code.
The pattern typically has these roles:
Handler Declares the common interface for handling requests and usually defines how to set the next handler.
Base Handler Optional class that stores the next handler and provides default forwarding behavior.
Concrete Handlers Decide whether they can handle the request or should pass it along.
Client Builds the chain and sends requests to the first handler.
Turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.
UI elements such as buttons, menu items, and shortcuts often trigger actions. If each UI class contains the action logic directly, it becomes coupled to business logic and hard to reuse. A copy button, context menu item, and keyboard shortcut may all need to perform the same operation.
The problem gets bigger when actions need to be queued, logged, scheduled, retried, or undone. A plain method call does not carry enough information to be treated as a first-class object.
Command wraps a request in an object with a common execution method, usually execute. The command stores the receiver, the operation to call, and any required parameters.
Invokers such as buttons or queues do not know the details of the operation. They just execute a command. This decouples the object that triggers the request from the object that performs the work.
Because commands are objects, they can be stored in history, placed in queues, serialized, retried, or paired with enough state to implement undo.
The pattern typically has these roles:
Command Declares the execution interface.
Concrete Command Stores the receiver and request details, then calls the receiver when executed.
Receiver Contains the real business logic.
Invoker Holds and triggers commands without knowing how they work internally.
Client Creates commands and connects them with receivers and invokers.
Lets you save and restore the previous state of an object without revealing the details of its implementation.
Applications often need undo, rollback, or checkpoints. A text editor, for example, should be able to restore a document to an earlier state.
Saving state from the outside can break encapsulation. The caretaker would need access to private fields, and any change to the object’s internals would also force changes in the snapshot logic.
Memento lets the object that owns the state create snapshots of itself. This object is called the originator. The snapshot is stored in a memento object.
Other objects, called caretakers, can store and later return mementos to the originator, but they do not inspect or modify the saved state. This keeps the originator responsible for its own internals while still allowing state history.
The pattern typically has these roles:
Originator Owns the important state and can create or restore snapshots.
Memento Stores a snapshot of the originator’s state. Its internal data should be visible only to the originator.
Caretaker Stores mementos and decides when to save or restore them, without depending on their contents.
Use the Memento pattern when:
Lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.
Imagine a customer eagerly awaiting a new iPhone at a store. They could check the store daily, often in vain, or the store could send frequent notifications to all customers, annoying those not interested. This creates a conflict: either the customer wastes time checking, or the store wastes resources and risks spamming uninterested customers.
The object that has some interesting state is called publisher; all other objects that want to track changes to the publisher’s state are called subscribers. This pattern suggests adding a subscription mechanism to the publisher class, so individual objects can subscribe to or unsubscribe from a stream of events coming from that publisher.
Whenever an event happens to the publisher, it goes over its subscribers and calls the specific notification method on their objects. The publisher doesn’t need to know much about subscribers’ concrete classes, so it’s crucial that they implement the same interface and that the publisher communicates with them only through that interface.
If you have multiple publishers, they can also implement the same publisher interface, so subscribers can observe them in a consistent way.

Use the Observer pattern when:
| Pros | Cons |
|---|---|
| Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher’s code (and vice versa if there’s a publisher interface) | Subscribers are notified in random order |
| You can establish relations between objects at runtime |
Lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.
A class may need to perform the same kind of task in several different ways. For example, a navigation app may calculate routes for walking, driving, cycling, or public transport.
If all algorithms are placed inside one class, it quickly fills with conditional logic. Every new algorithm changes that class, and clients may depend on details they should not know.
Strategy extracts each algorithm into its own class with a common interface. The original object, called the context, keeps a reference to a strategy and delegates the work to it.
The context does not know which concrete algorithm is being used. The client can choose the right strategy and even replace it at runtime. This keeps algorithms isolated and makes them easier to test, replace, or extend.
The pattern typically has these roles:
Strategy Declares the common interface for all supported algorithms.
Concrete Strategies Implement different versions of the algorithm.
Context Stores a strategy and delegates algorithm-specific work to it.
Client Chooses which strategy the context should use.
Lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.
When many objects communicate directly, dependencies can become tangled. A dialog window is a common example: buttons, text fields, checkboxes, and lists may all need to react to each other.
If each component knows about many other components, changing or reusing one of them becomes difficult. The communication logic is spread across the whole group instead of being easy to find.
Mediator moves communication logic into a separate mediator object. Components no longer call each other directly. Instead, they notify the mediator about events, and the mediator decides what other components should do.
This reduces coupling between components. They only need to know the mediator interface, while the mediator contains the coordination rules for a specific screen, workflow, or subsystem.
The pattern typically has these roles:
Mediator Declares methods that components use to notify it about events.
Concrete Mediator Coordinates components and contains the collaboration logic.
Components Perform their own work, but communicate with other components only through the mediator.
Client Creates the mediator and connects it with the components it coordinates.
Lets an object alter its behavior when its internal state changes. It appears as if the object changed its class.
An object may behave differently depending on its current state. For example, a document can be draft, moderated, or published, and the same operation may do different things in each state.
This is often implemented with large conditionals. As states and transitions grow, methods fill up with repeated checks, and adding a new state requires changes in many places.
State extracts state-specific behavior into separate state classes. The context stores a reference to the current state object and delegates behavior to it.
Each state class implements the behavior for that state and can decide when to transition the context to another state. This makes state-specific rules explicit and removes large conditional blocks from the context.
State is similar to Strategy in structure, but its purpose is different: strategies are usually chosen by the client, while states often change internally as the object evolves.
The pattern typically has these roles:
Context Stores the current state and delegates state-dependent behavior to it.
State Declares the common interface for all concrete states.
Concrete States Implement behavior for a specific state and may trigger transitions to other states.
Client Works with the context and usually does not manage state objects directly.
Lets you separate algorithms from the objects on which they operate.
Sometimes you need to add a new operation to many classes in an object structure. For example, a set of shapes may need export, reporting, validation, or analytics behavior.
Adding the operation directly to every class may pollute those classes with unrelated behavior. It can also be impossible if the classes belong to a library or are otherwise closed for modification.
Visitor moves the new operation into a separate visitor class. Each element in the object structure accepts a visitor and calls the visitor method that matches its own concrete type.
This is called double dispatch: the operation depends on both the visitor type and the element type. You can add new operations by creating new visitors without changing the element classes, as long as the element hierarchy is stable.
The pattern typically has these roles:
Visitor Declares visit methods for each concrete element type.
Concrete Visitor Implements one operation across all supported element types.
Element
Declares an accept method that receives a visitor.
Concrete Elements Call the matching visitor method and pass themselves as arguments.
Client Traverses the object structure and applies visitors to its elements.