Creational Patterns | | | | | |
Singleton | Managing global application state | A logger class that writes to a single log file | When you need separate instances | Different log files for different modules | Prototype, Factory Method |
Factory Method | Delegating object creation logic | A database access class that creates connections to different types of databases | Simple object creation | Instantiating a simple class that doesn’t require complex logic | Simple Constructor |
Abstract Factory | Creating families of related objects without specifying their concrete classes | UI toolkit that provides widgets for multiple operating systems | No need for multiple object families | An application that only runs on one operating system and doesn’t need different styles of widgets | Simple Constructor, Builder |
Builder | Creating complex objects with multiple optional parameters | Building an SQL query with various optional filters and parameters | When object creation is straightforward | Instantiating an object with only mandatory fields and no optional settings | Simple Constructor |
Prototype | Creating new objects by copying existing ones | Duplicating user-configured settings in a complex configuration object | When objects are simple to create | Creating a new default configuration object that doesn’t require variation | Simple Constructor |
Structural Patterns | | | | | |
Adapter | Allowing classes with incompatible interfaces to work together | Wrapping an old API to match a new interface expected by modern code | When you control the interfaces | Creating a new system where you define all the interfaces to be compatible from the start | None needed (use direct implementation) |
Bridge | Separating an abstraction from its implementation so they can vary independently | A game engine that can run with different rendering APIs (OpenGL, DirectX) | No need for varying abstractions | A script that performs a single, specific task without the need for interchangeable back-end processes | None needed (use direct implementation) |
Composite | Treating individual and composite objects uniformly | A graphic editor that handles both individual shapes and groups of shapes | No need to treat objects uniformly | A simple application where objects are always treated individually | None needed (use direct implementation) |
Decorator | Adding responsibilities to objects dynamically without changing their implementation | Adding new encryption layers to a data stream without changing the original data source class | When subclassing is more appropriate | Extending a class hierarchy with new subclass for each specific feature | Subclassing |
Facade | Providing a simple interface to a complex subsystem | A high-level interface for video conversion that hides the complex underlying libraries | When you need to work with the complexity directly | When you need to perform complex operations with fine-grained control | None needed (work directly with the complex subsystem) |
Flyweight | Sharing fine-grained objects to reduce memory usage | Reusing character objects in a word processor to save memory | When memory usage is not a concern | An application that creates a small number of heavy objects that don’t share state | None needed (use direct instantiation) |
Proxy | Controlling access to an object, lazy instantiation, or implementing logging | A virtual proxy for a large image that is only loaded into memory when actually needed | When direct object access is acceptable | Accessing a small, in-memory database where proxying would add unnecessary overhead | None needed (use direct access) |
Behavioral Patterns | | | | | |
Chain of Responsibility | Passing requests along a chain of handlers until one handles it | Event propagation in a GUI framework, where an event travels up through a component hierarchy until it’s handled | When only one handler should be used | Processing a request that should be handled by a single, specific handler | Command |
Command | Encapsulating a request as an object | Undo/Redo operations in a text editor, where each edit action is a command object | When actions are simple and can be executed directly | Simple callback functions for button clicks in a simple GUI | Strategy |
Interpreter | Defining a way to evaluate sentences in a language | A formula parser in a spreadsheet application that interprets cell formulas | When the language is too complex for the pattern | Parsing a full-featured programming language with complex syntax and semantics | Parser / Compiler library |
Iterator | Providing a way to access elements of a collection sequentially without exposing its underlying representation | Iterating over a collection of objects in an application without exposing the collection’s structure | When the collection is simple and can be accessed directly | Accessing elements in a fixed array with known dimensions | None needed (use direct access) |
Mediator | Reducing direct communication between classes to make them less dependent on each other | A chat application where the server acts as a mediator between clients | When direct communication is preferred for simplicity | A two-player game where players interact directly without a central mediator | None needed (use direct communication) |
Memento | Capturing and externalizing an object’s internal state without violating encapsulation | Saving the state of a complex object to restore it later, like a snapshot feature in a virtual machine | When exposing the internal state is not problematic | A simple data structure where the state can be easily managed and doesn’t need encapsulation | State pattern (if behavior changes are needed) |
Observer | Allowing subscribers to be notified of changes in another object | A weather station application that updates multiple displays when the weather data changes | When changes do not need to be communicated in real-time | Logging information where updates can be checked periodically without instant notification | Polling or Callbacks |
State | Allowing an object to change its behavior when its internal state changes | A network connection that changes its behavior based on the connection state (connected, disconnected, attempting to connect) | When state changes are so simple that a state machine is overkill | A light bulb that is either on or off, with a simple toggle switch | None needed (use direct conditionals) |
Strategy | Encapsulating different algorithms or behaviors to be selected at runtime | Different sorting algorithms that can be selected based on the size and type of the data | When there is only one algorithm or behavior | A service that always uses the same algorithm because it’s the only one suitable for its purpose | None needed (implement the algorithm directly) |
Template Method | Defining the skeleton of an algorithm and letting subclasses redefine certain steps | A data miner that provides a template for parsing, analyzing, and reporting data, but lets subclasses define the parsing logic | When the algorithm doesn’t vary or when there is little to no common behavior | A simple task that doesn’t require varying steps or can be completed in a single function | Strategy (if different algorithms are needed) |