Introduction
Design patterns are typical solutions to common problems in software design. They represent best practices used by experienced object-oriented software developers.
The Gang of Four (GoF) design patterns are a set of 23 foundational software design patterns introduced in the book “Design Patterns: Elements of Reusable Object-Oriented Software” by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.
What is a Design Pattern?
Design Patterns are reusable solutions to common problems in software design. They are like templates or blueprints that help developers solve issues in a structured and efficient way. Instead of reinventing the wheel, you can use these tried-and-tested patterns to handle typical scenarios in software development.
Categories of Design Patterns
The Gang of Four (GoF) design patterns are 23 foundational patterns classified into three categories: Creational, Structural, and Behavioral.
1. Creational Patterns
These patterns deal with the object creation. They help make a system independent of how its objects are created, composed, and represented.
2. Structural Patterns
These patterns deal with object composition or the structure of objects. They help ensure that if one part of a system changes, the entire structure doesn’t need to change.
3. Behavioral Patterns
These patterns focus on communication between objects, or the way objects interact and distribute responsibilities.
GoF Design Patterns Cheat Sheet
Creational Patterns
Pattern | Description |
---|---|
Singleton | Ensures a class has only one instance and provides a global point of access to it. |
Factory Method | Defines an interface for creating an object, but lets subclasses alter the type of objects that will be created. |
Abstract Factory | Provides an interface for creating families of related or dependent objects without specifying their concrete classes. |
Builder | Separates the construction of a complex object from its representation, allowing the same construction process to create different representations. |
Prototype | Creates new objects by copying an existing object, known as the prototype. |
Structural Patterns
Pattern | Description |
---|---|
Adapter | It allows incompatible interfaces to work together by converting a class’s interface into another interface that the client expects. |
Bridge | Decouples an abstraction from its implementation so that the two can vary independently. |
Composite | Composes objects into tree structures to represent part-whole hierarchies, allowing clients to treat individual objects and compositions of objects uniformly. |
Decorator | Adds additional responsibilities to an object dynamically without altering its structure. |
Facade | It provides a simplified interface to a complex subsystem, making it easier to use. |
Flyweight | Reduces the cost of creating and manipulating a large number of similar objects by sharing common data among them. |
Proxy | Provides a surrogate or placeholder for another object to control access to it. |
Behavioral Patterns
Pattern | Description |
---|---|
Chain of Responsibility | Passes a request along a chain of handlers, allowing each handler to either process the request or pass it to the next handler in the chain. |
Command | It encapsulates a request as an object, thereby allowing for the parameterization of clients with queues, requests, and operations. |
Interpreter | Defines a representation for a language’s grammar and provides an interpreter to deal with this grammar. |
Iterator | Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. |
Mediator | Defines an object that encapsulates how a set of objects interact, promoting loose coupling by keeping objects from referring to each other explicitly. |
Memento | Captures and externalizes an object’s internal state so that it can be restored to this state later without violating encapsulation. |
Observer | Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. |
State | Allows an object to alter its behavior when its internal state changes, appearing to change its class. |
Strategy | Defines a family of algorithms, encapsulates each one, and makes them interchangeable. |
Template Method | Defines the skeleton of an algorithm in a method, deferring some steps to subclasses, allowing subclasses to redefine certain steps of the algorithm without changing its structure. |
Visitor | Represents an operation to be performed on the elements of an object structure, allowing new operations to be added without changing the classes of the elements on which it operates. |
Delegation | Delegates operations to a helper object to achieve a task, promoting reuse and flexibility. |
Sure, here’s an updated explanation of each GoF design pattern, including its definition, when to use it, and multiple real-world examples.
Creational Patterns
1. Singleton
Definition: Ensures a class has only one instance and provides a global point of access to it.
When to Use: When you need to control access to a shared resource, such as a configuration object or a connection pool.
Real-World Examples:
- Logging Service: A logging utility often operates as a singleton, ensuring all parts of an application log messages to a single point of control.
- Database Connection: Managing a single connection to a database that is used throughout an application.
2. Factory Method
Definition: Provides an interface for creating objects but allows subclasses to alter the type of objects that will be created.
When to Use: When the exact type of the object is determined by subclasses.
Real-World Examples:
- Document Creation: A text editor that can create different types of documents (e.g., Word, PDF).
- Shape Creation: A graphic application that creates different shapes (e.g., circles, squares) based on user input.
3. Abstract Factory
Definition: Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
When to Use: When you need to create families of related objects without having to specify their concrete classes.
Real-World Examples:
- UI Themes: Creating user interface components (buttons, text fields) that conform to a specific theme (e.g., light or dark mode).
- Database Operations: A system that needs to interact with multiple databases (e.g., MySQL, PostgreSQL) and create objects specific to each database type.
4. Builder
Definition: Separates the construction of a complex object from its representation, allowing the same construction process to create different representations.
When to Use: When constructing complex objects with many parts and varying configurations.
Real-World Examples:
- Meal Construction: Building a custom meal at a restaurant where you choose the ingredients.
- Vehicle Manufacturing: Constructing different types of vehicles (cars, bikes) using the same assembly process.
5. Prototype
Definition: Creates new objects by copying an existing object, known as the prototype.
When to Use: When creating new instances of objects that are similar or when the cost of creating objects from scratch is high.
Real-World Examples:
- Document Templates: Creating new documents by copying an existing template.
- Game Character Creation: Cloning a character in a video game to create a new one with similar attributes.
Structural Patterns
6. Adapter
Definition: Allows incompatible interfaces to work together by converting the interface of a class into another interface that the client expects.
When to Use: When you want to use an existing class but its interface is not compatible with the rest of your code.
Real-World Examples:
- Power Adapter: Using a power adapter to plug an American electrical appliance into a European socket.
- Software Integration: Adapting a legacy system to work with a new API without altering the legacy system.
7. Bridge
Definition: Decouples an abstraction from its implementation so that the two can vary independently.
When to Use: When you want to separate an abstraction from its implementation so that they can be developed independently.
Real-World Examples:
- Remote Control: A remote control that works with multiple devices (e.g., TV, DVD player).
- Vehicle Control System: A control system that can operate different types of vehicles (e.g., cars, trucks) with the same interface.
8. Composite
Definition: Composes objects into tree structures to represent part-whole hierarchies, allowing clients to treat individual objects and compositions of objects uniformly.
When to Use: When dealing with tree structures of objects and want to treat both individual objects and compositions uniformly.
Real-World Examples:
- File System: A file system where both files and folders are treated uniformly, and folders can contain files or other folders.
- Organization Hierarchy: A company’s organizational structure where departments contain teams, and teams contain employees.
9. Decorator
Definition: Adds additional responsibilities to an object dynamically without altering its structure.
When to Use: When you want to add functionalities to individual objects without affecting other objects of the same class.
Real-World Examples:
- Pizza Toppings: Adding toppings to a pizza without changing the pizza itself.
- UI Enhancements: Adding scrollbars or borders to a window without altering the window’s core functionality.
10. Facade
Definition: Provides a simplified interface to a complex subsystem, making it easier to use.
When to Use: When you want to provide a simple interface to a complex system.
Real-World Examples:
- Home Theater System: A universal remote control that simplifies the operation of a home theater system.
- Web API: A single API endpoint that internally calls multiple services to provide a simplified response.
11. Flyweight
Definition: Reduces the cost of creating and manipulating a large number of similar objects by sharing common data among them.
When to Use: When you need to efficiently handle a large number of similar objects.
Real-World Examples:
- Text Editors: Storing character formatting data (e.g., font, color) only once and sharing it among multiple text instances.
- Game Development: Reusing similar game objects like trees or buildings across different parts of a game map.
12. Proxy
Definition: Provides a surrogate or placeholder for another object to control access to it.
When to Use: When you need to control access to an object, for example, for security reasons, lazy initialization, or remote access.
Real-World Examples:
- Bank ATM: Acting as a proxy for bank accounts, allowing users to access their accounts without directly interacting with the bank.
- Virtual Proxy: Loading a large image or resource only when it is actually needed.
Behavioral Patterns
13. Chain of Responsibility
Definition: Passes a request along a chain of handlers, allowing each handler to either process the request or pass it to the next handler in the chain.
When to Use: When you have multiple objects that can handle a request, but you want to leave it to the objects themselves to decide which one will handle it.
Real-World Examples:
- Customer Support: Escalating a customer’s issue through different levels of support until it is resolved.
- Event Handling: Handling UI events like clicks or key presses in a sequence of handlers.
14. Command
Definition: Encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations.
When to Use: When you want to decouple the sender of a request from the object that performs the action.
Real-World Examples:
- Remote Control: Storing button presses as commands to be executed later.
- Task Scheduling: Queuing up tasks to be executed by a task scheduler.
15. Interpreter
Definition: Defines a representation for a language’s grammar and provides an interpreter to deal with this grammar.
When to Use: When you need to interpret a language or execute scripts.
Real-World Examples:
- Regular Expressions: Interpreting and executing pattern-matching rules.
- Mathematical Expression Evaluator: Parsing and evaluating math expressions.
16. Iterator
Definition: Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
When to Use: When you need to traverse a collection of objects without exposing its internal structure.
Real-World Examples:
- List Iteration: Traversing through a list of items like an array or a collection.
- File Directory Traversal: Iterating over files in a directory structure.
17. Mediator
Definition: Defines an object that encapsulates how a set of objects interact, promoting loose coupling by keeping objects from referring to each other explicitly.
When to Use: When you want to reduce the complexity of communication between multiple objects.
Real-World Examples:
- Air Traffic Control: Acting as a mediator between airplanes to prevent collisions.
- Chat Room: A chat application where the server mediates the communication between users.
18. Memento
Definition: Captures and externalizes an object’s internal state so that it can be restored to this state later without violating encapsulation.
When to Use: When you need to save and restore an object’s state.
Real-World Examples:
- Undo Functionality: Implementing undo operations in text editors or games.
- Game Save State: Saving and loading the state of a game to continue later.
19. Observer
Definition: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
When to Use: When multiple objects need to be notified and updated automatically when another object changes.
Real-World Examples:
- News Subscription: Notifying subscribers when a new article is published.
- Event Listeners: Updating UI components when data changes in an application.
20. State
Definition: Allows an object to alter its behavior when its internal state changes, appearing to change its class.
When to Use: When an object’s behavior depends on its state and it must change its behavior at runtime.
Real-World Examples:
- Traffic Light: Changing behavior (color) based on its state (red
Continuing from where we left off:
20. State
Definition: Allows an object to alter its behavior when its internal state changes, appearing to change its class.
When to Use: When an object’s behavior depends on its state and it must change its behavior at runtime.
Real-World Examples:
- Traffic Light: A traffic light changes behavior (color) based on its state (red, yellow, green).
- Media Player: A media player changes its behavior based on whether it’s in playing, paused, or stopped state.
21. Strategy
Definition: Defines a family of algorithms, encapsulates each one, and makes them interchangeable. The strategy pattern allows the algorithm to vary independently from clients that use it.
When to Use: When you have multiple algorithms for a specific task and you want to swap them easily.
Real-World Examples:
- Sorting Algorithms: Different sorting strategies (e.g., quick sort, merge sort) that can be selected at runtime.
- Payment Methods: An e-commerce platform where users can choose between different payment strategies (credit card, PayPal, etc.).
22. Template Method
Definition: Defines the skeleton of an algorithm in a method, deferring some steps to subclasses. This allows subclasses to redefine certain steps of the algorithm without changing its structure.
When to Use: When you have an algorithm that needs to be extended by subclasses, but you want to ensure that the structure of the algorithm remains the same.
Real-World Examples:
- Cooking Recipes: A general recipe template where specific steps (e.g., add spices, cook meat) are defined by subclasses.
- Document Processing: A document processing system where the general structure (e.g., open, process, close) is fixed, but the processing step can vary.
23. Visitor
Definition: Represents an operation to be performed on the elements of an object structure. The visitor pattern allows you to add further operations to this structure without modifying its elements.
When to Use: When you need to perform operations on elements of a complex object structure, and you want to keep these operations separate from the object structure itself.
Real-World Examples:
- Tax Calculation: Different tax calculations for different product types in an inventory system.
- Syntax Tree Evaluation: Applying operations like type-checking or code generation to different nodes in a syntax tree.
Conclusion
Understanding and applying design patterns is essential for creating efficient, maintainable, and scalable software. This cheat sheet provides a quick reference to the Gang of Four design patterns, helping you to choose the appropriate pattern for your design problems. Keep this guide handy to make the most of design patterns in your software development.