Master the most important design patterns with theory explanations and practical code examples. Learn when to use each pattern and how they solve real-world problems.
Showing 21 patterns
Ensures a class has only one instance and provides a global point of access to it.
Common Use Cases:
Defines an interface for creating objects, but lets subclasses decide which class to instantiate.
Separates the construction of a complex object from its representation, allowing step-by-step creation.
Defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime without modifying the client.
Defines a one-to-many dependency so when one object changes state, all its dependents are notified and updated automatically.
Attach additional responsibilities to an object dynamically, providing a flexible alternative to subclassing.
Convert the interface of a class into another interface clients expect, letting incompatible classes work together.
Provide a simplified interface to a complex subsystem, hiding internal complexity behind a single entry point.
Define the skeleton of an algorithm in a base class, deferring specific steps to subclasses without changing the overall structure.
Encapsulate a request as an object, enabling undo/redo, request queuing, logging, and decoupling of sender from receiver.
Allow an object to alter its behaviour when its internal state changes, appearing to change its class at runtime.
Pass requests along a chain of handlers, where each handler decides to process the request or pass it to the next handler.
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
Allows cloning existing objects without coupling your code to their specific classes, ideal for expensive object creation.
Provides a surrogate or placeholder for another object to control access to it, often for security or lazy loading.
Composes objects into tree structures to represent part-whole hierarchies, treating individual objects and compositions uniformly.
Decouples an abstraction from its implementation so that the two can vary independently, avoiding an exponential class explosion.
Reduces chaotic dependencies between objects by forcing them to communicate via a central mediator object.
Captures and externalizes an object's internal state so that the object can be restored to this state later without violating encapsulation.
Supports large numbers of fine-grained objects efficiently by sharing common parts of state across multiple objects.
Allows adding new operations to existing object structures without modifying the structures themselves.