Design Patterns - Behavioral
Behavioral patterns take care of effective communication and the assignment of responsibilities between objects.
Chain of responsibility
: A way of passing a request between a chain of objectsCommand
: Encapsulate a command request as an objectInterpreter
: A way to include language elements in a programIterator
: Sequentially access the elements of a collectionMediator
: Defines simplified communication between classesMemento
: Capture and restore an object's internal stateNull Object
: Designed to act as a default value of an objectObserver
: A way of notifying change to a number of classesState
: Alter an object's behavior when its state changesStrategy
: Encapsulates an algorithm inside a classTemplate method
: Defer the exact steps of an algorithm to a subclassVisitor
: Defines a new operation to a class without change
1. Chain of Responsibility
- As a developer, I can pass a request through a chain of handler objects (e.g., an event pipeline), in order to process it at the appropriate level without tightly coupling the sender to the receiver.
- As a user, I can interact with a system (e.g., a helpdesk ticketing system) that routes my request automatically, in order to get the right response without needing to know the internal process.
- As a project manager, I can implement flexible workflows (e.g., approval chains), in order to adapt to changing business rules without rewriting core logic.
Explanation: The Chain of Responsibility pattern facilitates passing requests along a chain of handlers, focusing on communication flow. Each handler decides whether to process the request or pass it to the next handler, decoupling the sender from the receiver.
2. Command
- As a developer, I can encapsulate a request as an object (e.g., a button click action), in order to queue, log, or undo operations easily.
- As a user, I can perform actions (e.g., undo/redo in a text editor), in order to have a seamless and flexible interaction with the system.
- As a project manager, I can add new commands (e.g., new toolbar actions) without modifying existing code, in order to support rapid feature development.
Explanation: The Command pattern encapsulates requests as objects, enabling flexible invocation and responsibility assignment. It supports operations like queuing, logging, and undoing by treating commands as first-class objects.
3. Interpreter
- As a developer, I can define a grammar and interpreter for a language (e.g., SQL query parser), in order to process complex expressions systematically.
- As a user, I can input custom rules or scripts (e.g., in a rule-based engine), in order to customize system behavior without needing to understand its internals.
- As a project manager, I can support domain-specific languages for specific tasks, in order to enable non-developers to define business logic efficiently.
Explanation: The Interpreter pattern defines how to interpret a language’s grammar, focusing on object interactions for language processing. It allows programs to evaluate sentences in a custom language or grammar.
4. Iterator
- As a developer, I can traverse a collection (e.g., a list of items) without exposing its internal structure, in order to write cleaner and more reusable code.
- As a user, I can navigate through data (e.g., scrolling through a playlist), in order to access items sequentially without complexity.
- As a project manager, I can ensure consistent iteration across different data structures, in order to reduce bugs and simplify maintenance.
Explanation: The Iterator pattern provides a way to access elements of a collection sequentially, managing how objects interact with collections without exposing their underlying representation.
5. Mediator
- As a developer, I can centralize communication between objects (e.g., UI components in a form), in order to reduce direct dependencies and simplify interactions.
- As a user, I can interact with a cohesive interface (e.g., a chat system), in order to perform actions without managing complex object relationships.
- As a project manager, I can streamline system updates by modifying a single mediator, in order to reduce refactoring efforts across multiple components.
Explanation: The Mediator pattern simplifies communication between objects by centralizing interactions through a mediator object, reducing direct dependencies and improving maintainability.
6. Memento
- As a developer, I can capture and restore an object’s state (e.g., game progress), in order to support features like undo or checkpointing.
- As auser, I can revert to a previous state (e.g., undo in a drawing app), in order to correct mistakes seamlessly.
- As a project manager, I can add state-saving features without altering core logic, in order to enhance user experience with minimal development overhead.
Explanation: The Memento pattern manages object state changes and restoration, focusing on interaction for state capture. It allows saving and restoring an object’s state without exposing its internals.
7. Observer
- As a developer, I can notify multiple objects (e.g., UI components) of state changes (e.g., data updates), in order to keep the system synchronized dynamically.
- As a user, I can see real-time updates (e.g., stock ticker), in order to stay informed without manual refreshes.
- As a project manager, I can ensure scalable event-driven systems, in order to support new features without disrupting existing components.
Explanation: The Observer pattern enables one-to-many notifications of state changes, focusing on object communication. It allows multiple objects to react to changes in a subject’s state.
8. State
- As a developer, I can change an object’s behavior based on its state (e.g., a media player’s play/pause state), in order to manage complex logic cleanly.
- As a user, I can interact with a system that adapts to context (e.g., a vending machine’s state), in order to have intuitive responses.
- As a project manager, I can add new states without modifying core logic, in order to support evolving requirements efficiently.
Explanation: The State pattern allows an object to change its behavior when its internal state changes, managing internal responsibilities by delegating behavior to state objects.
9. Strategy
- As a developer, I can swap algorithms at runtime (e.g., sorting methods), in order to make behavior interchangeable without altering the client code.
- As a user, I can select different options (e.g., compression algorithms in a file archiver), in order to customize functionality based on my needs.
- As a project manager, I can introduce new algorithms without changing existing systems, in order to support rapid feature expansion.
Explanation: The Strategy pattern encapsulates algorithms to make them interchangeable, focusing on responsibility delegation. It allows clients to choose behaviors dynamically.
10. Template Method
- As a developer, I can define a common algorithm structure (e.g., a report generator), in order to reuse shared logic while allowing subclasses to customize steps.
- As a user, I can benefit from consistent processes (e.g., document processing workflows), in order to rely on predictable outcomes.
- As a project manager, I can extend functionality by adding new subclasses, in order to avoid modifying tested base logic.
Explanation: The Template Method pattern defines the skeleton of an algorithm, deferring specific steps to subclasses, managing responsibility while ensuring a consistent structure.
11. Visitor
- As a developer, I can add new operations to a class hierarchy (e.g., exporting data in multiple formats), in order to extend functionality without modifying existing classes.
- As a user, I can perform varied operations on data (e.g., rendering graphics in different styles), in order to achieve diverse outputs without altering the data structure.
- As a project manager, I can introduce new features without risking existing code stability, in order to reduce maintenance costs and technical debt.
Explanation: The Visitor pattern separates operations from objects, enabling new operations without modifying classes, focusing on interaction by delegating behavior to visitor objects.
Done!
Thanks for reading! We hope this overview of behavioral design patterns will help you appreciate the usefulness and usecases of these patterns in software development.