Creational Patterns
Creational patterns separate the concern of how objects come into existence from how they are used. This separation lets you change the creation strategy—from a single shared instance, to a family of related objects, to a fully configured complex object—without touching the code that consumes those objects.Factory Method
The Factory Method pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. You use it when you need to decouple object creation from the code that uses the object, and when you want to support different object types without modifying calling code. Example: A car factory creates different vehicle types based on a string parameter, so the rest of your application never callsnew Sedan() or new SUV() directly.
factory.createCar(...).
Abstract Factory
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. Think of it as a factory where the factory itself is abstracted: each concrete factory implementation produces a coordinated set of products. Key insight: Each concrete factory creates a consistent suite of objects. AModernFurnitureFactory produces modern tables and modern chairs together; a ClassicalFurnitureFactory produces the classical variants. You swap the entire product family by swapping the factory.
Builder
The Builder pattern separates the construction of a complex object from its representation, so the same construction process can produce different representations. You use it when an object has many optional configuration parameters that would otherwise lead to telescoping constructors. Example: Building aComputer with optional CPU, memory, and storage choices using a fluent builder API:
Singleton
The Singleton pattern ensures a class has exactly one instance and provides a global access point to it. You use it for shared resources like database connection pools, configuration registries, or logging systems where multiple instances would cause resource waste or inconsistency. Thread-safe lazy initialization (double-checked locking):volatile and double-checked locking, or the eager initialization variant above.
Prototype
The Prototype pattern creates new objects by cloning an existing instance. You use it when object creation is expensive (e.g., involves a database query or heavy computation), and a copy with slight modifications is cheaper than building from scratch. In Java, implementCloneable and override clone(); in Go, return a copy of the struct.
Structural Patterns
Structural patterns describe how classes and objects are assembled to form larger, more complex structures. They enable you to change the composition of objects at runtime, add responsibilities without subclassing, and wrap incompatible interfaces—all without breaking existing code.Adapter
The Adapter pattern converts one interface into another that a client expects, making otherwise incompatible classes work together. You use it most often when integrating legacy code with a new system. Example: An old printer only speaksprintOldFormat(), but your new system calls printNewFormat(). An adapter bridges the gap:
NewComputer exclusively; the adapter handles translation in one place.
Decorator
The Decorator pattern attaches additional responsibilities to an object dynamically. It extends behavior through composition rather than inheritance, which means you can mix and stack decorators at runtime without creating an explosion of subclasses. It follows the open/closed principle: open for extension, closed for modification. The four roles are: Component (interface), ConcreteComponent (base object), Decorator (abstract wrapper holding a reference to a Component), and ConcreteDecorator (adds the actual new behavior).InputStream hierarchy (e.g., BufferedInputStream wrapping FileInputStream) is a canonical real-world example.
Proxy
The Proxy pattern provides a surrogate or placeholder for another object to control access to it. You use it for lazy initialization (don’t load a heavy resource until first use), access control, caching, and logging. Example: AProxyImage defers loading from disk until display() is actually called:
Facade
The Facade pattern provides a simplified, unified interface to a complex subsystem. Your clients interact with the facade rather than with the dozens of classes underneath. Common examples include aHomeTheaterFacade that wraps amplifier, projector, DVD player, and lights behind a single watchMovie() call, or a service layer that hides database, cache, and external API calls from your controller.
Composite
The Composite pattern composes objects into tree structures to represent part-whole hierarchies. It lets you treat individual objects and compositions uniformly—clients call the same interface whether they hold a leaf or a branch.Bridge
The Bridge pattern decouples an abstraction from its implementation so the two can vary independently. Instead of inheriting a color into every shape subclass (creating an M×N class explosion), you inject the color implementation as a dependency:Flyweight
The Flyweight pattern uses sharing to support a large number of fine-grained objects efficiently. You split object state into intrinsic (shared, immutable) and extrinsic (context-specific, passed in at use time). A text editor storing per-character font objects is the canonical example: instead of millions ofCharacter objects each holding a font reference, you share a pool of flyweight font objects.
Behavioral Patterns
Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects. They describe not just patterns of objects and classes but also the patterns of communication between them.Observer
The Observer pattern defines a one-to-many dependency so that when one object changes state, all its dependents are notified and updated automatically. You use it for event systems, pub/sub messaging, and any situation where multiple components need to react to state changes.java.util.EventListener, reactive streams, and message brokers like Kafka all implement variants of this pattern.
Strategy
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. The algorithm varies independently from the clients that use it. You use it to replace conditional logic (if/switch on type) with polymorphism.Command
The Command pattern encapsulates a request as an object, letting you parameterize clients with different requests, queue or log requests, and support undoable operations. Each command object implements anexecute() method; an invoker stores and triggers commands without knowing their implementation. Text editor undo/redo systems and transaction log replay are classic use cases.
Iterator
The Iterator pattern provides a sequential way to access elements of a collection without exposing its internal representation. In Java,java.util.Iterator is the canonical implementation. You use it to traverse lists, trees, graphs, and streams in a uniform way regardless of the underlying data structure.
Template Method
The Template Method pattern defines the skeleton of an algorithm in a base class, deferring some steps to subclasses. Subclasses can override specific steps without changing the algorithm’s structure. A data-processing pipeline might definereadData(), processData(), and writeData() in a template—concrete subclasses provide each step for CSV, JSON, or database sources.
State
The State pattern allows an object to alter its behavior when its internal state changes. The object appears to change its class. Instead of largeif/switch statements checking a status field, you represent each state as a class and delegate behavior to the current state object. An order management system with states like PendingPayment, Processing, Shipped, and Delivered is a good fit.
Chain of Responsibility
The Chain of Responsibility pattern passes a request along a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain. Adding a new handling step means inserting a new handler node without modifying existing handlers. HTTP middleware pipelines and logging level filters are everyday examples.Visitor
The Visitor pattern lets you add operations to an object structure without modifying the objects themselves. You define aVisitor interface with a visit() method for each element type, and each element calls visitor.visit(this). This is useful when you have a stable object hierarchy but frequently add new operations—for example, code analysis tools that traverse an AST.
Mediator
The Mediator pattern reduces chaotic dependencies between objects by routing all communication through a central mediator. Objects no longer refer to each other directly; they communicate via the mediator. This turns an M×N communication graph into M+N relationships. Chat room servers and air traffic control systems are classic examples.Memento
The Memento pattern captures and externalizes an object’s internal state so the object can be restored to that state later, without violating encapsulation. The originator creates a memento, a caretaker stores it, and the originator can restore from it. Text editors with multi-level undo use this pattern.Interpreter
The Interpreter pattern defines a grammar for a language and provides an interpreter to deal with that grammar. Each grammar rule becomes a class. You use it for DSLs, regular expression engines, and SQL-like query parsers. It is rarely used in production because parser combinator libraries and grammar tools are usually a better choice for complex languages.The three most commonly used patterns in backend service development are Singleton, Factory Method, and Observer. Among structural patterns, Proxy, Decorator, and Adapter are the most frequently encountered. Start with these before diving into the less common ones like Flyweight or Interpreter.