Design Patterns
All 23 GoF patterns. Popularity reflects how often each pattern shows up in real production code, not how useful it is to know.
creational
Abstract Factory
Creates families of related objects without specifying their concrete classes. Useful when the system needs to be independent of how its products are created and composed.
Builder
Separates the construction of a complex object from its representation. The same construction process can produce different results depending on the builder used.
Factory Method
Defines an interface for creating an object but lets subclasses decide which class to instantiate. Defers instantiation to subclasses without coupling to concrete types.
Prototype
Creates new objects by copying an existing one. Useful when instantiation is expensive and a usable object already exists that can be cloned and adjusted.
Singleton
Ensures a class has only one instance and provides a global access point to it. Works well for immutable shared resources; causes problems when the instance is mutable.
structural
Adapter
Converts one interface into another that clients expect. Lets incompatible interfaces work together without modifying the existing code on either side.
Bridge
Decouples an abstraction from its implementation so both can vary independently. Avoids a class explosion when multiple dimensions of variation need to combine.
Composite
Composes objects into tree structures to represent part-whole hierarchies. Lets clients treat individual objects and compositions of objects uniformly.
Decorator
Attaches additional responsibilities to an object at runtime. A flexible alternative to subclassing for extending behavior without modifying the original class.
Facade
Provides a simplified interface to a complex subsystem. Reduces coupling between client code and internal components, making the subsystem easier to use and change.
Flyweight
Shares state across large numbers of fine-grained objects to reduce memory use. Splits object state into intrinsic (shared) and extrinsic (passed in per use).
Proxy
Provides a placeholder for another object to control access to it. Common uses: lazy initialization, access control, logging, and caching without touching the real object.
behavioral
Chain of Responsibility
Passes a request along a chain of handlers. Each handler decides to process the request or forward it. Decouples senders from receivers without hardcoding which handler responds.
Command
Encapsulates a request as an object. Enables queuing, logging, and undoable operations by treating actions as first-class values that can be stored and passed around.
Interpreter
Defines a grammar and an interpreter for a simple language. Rarely built from scratch today — parser-combinator libraries and parser generators cover this use case more reliably.
Iterator
Provides sequential access to elements of a collection without exposing its internal representation. Built into most modern languages as a core protocol, rarely implemented manually.
Mediator
Centralizes communication between objects through a mediator object. Reduces direct dependencies, but concentrates logic — a mediator that grows too large becomes a god object.
Memento
Captures an object's internal state so it can be restored later, without exposing that state to the outside. The basis of undo/redo in editors and command processors.
Observer
Defines a one-to-many dependency so that when one object changes state, all dependents are notified. The foundation of event systems and reactive programming.
State
Lets an object change its behavior when its internal state changes. Replaces large conditionals on state flags with distinct state objects that handle behavior directly.
Strategy
Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Lets the algorithm vary independently from the clients that use it.
Template Method
Defines the skeleton of an algorithm in a base class and defers specific steps to subclasses. Subclasses override individual steps without changing the overall structure.
Visitor
Lets you add operations to objects without modifying them. Separates an algorithm from the object structure it operates on, at the cost of making it hard to add new types.