Design patterns
Creational Patterns
5 entriesPatterns that control how objects get built, so callers depend on what they need rather than on which concrete class supplies it.
- Factory MethodLet a subclass or a supplied function decide which concrete object to create, so shared workflow code depends only on an interface.
- Abstract FactoryCreate families of related objects through one interface so client code always gets a matching set and never names the concrete classes.
- BuilderAssemble a complex object through named, step-by-step calls and validate it once in build(), instead of a constructor with many parameters.
- PrototypeCreate new objects by copying a configured existing instance, so callers get a ready-made variant without knowing its class or setup.
- SingletonGuarantee one instance of a class per process with a global access point. Usually better replaced by one instance created at startup and injected.
Structural Patterns
7 entriesPatterns that combine objects and classes into larger structures while keeping each part replaceable and its interface small.
- AdapterWrap an incompatible class in an object that exposes the interface your code expects, so you can use it without changing either side.
- BridgeSplit a class that varies along two dimensions into two hierarchies joined by composition, so each side grows without multiplying subclasses.
- CompositeTreat single objects and nested groups of them through one interface, so code can walk a tree of any depth without checking node types.
- DecoratorWrap an object in another object with the same interface that adds behavior before or after delegating, so features stack without subclassing.
- FacadeGive a complex subsystem one small entry point for a common task, so callers stop orchestrating its classes and calling them in the right order.
- FlyweightShare one immutable object for state that many objects have in common, and pass the per-object rest in, to cut memory when instances number in the millions.
- ProxyPut a stand-in with the same interface in front of an object to control access to it: create it lazily, check permissions, or reach it remotely.
Behavioral Patterns
10 entriesPatterns that assign responsibilities and route requests between objects, so behavior can change without rewriting the code that triggers it.
- Chain of ResponsibilityPass a request along a chain of handlers until one decides it, so the sender never knows which handler acts or how many exist.
- CommandWrap an action and its arguments in an object so you can queue, log, retry or undo it separately from the code that triggers it.
- IteratorWalk the elements of a collection one at a time through a standard interface, without exposing how the collection stores or fetches them.
- MediatorRoute interactions between a group of components through one coordinator so they stop referencing each other and the rules live in one place.
- MementoCapture an object's internal state in an opaque snapshot so it can be restored later without exposing that state to the code holding the snapshot.
- ObserverLet an object announce its changes to a list of subscribers it does not know, so new reactions plug in without editing the source of the change.
- StateMove each mode of an object into its own class so behavior and transitions change with the mode instead of branching on a status field.
- StrategyPut each interchangeable algorithm behind one interface so the caller picks a behavior at runtime without branching on it.
- Template MethodFix an algorithm's sequence of steps in a base class and let subclasses fill in or override individual steps without changing the order.
- VisitorAdd new operations over a fixed set of node types without editing those types, by routing each node to a type-specific method on a visitor object.
Resilience Patterns
6 entriesPatterns for calls that can fail, hang or come back wrong: bound the wait, count the failures, space the repeats, and continue with a lesser answer.
- TimeoutGive every remote call a deadline shorter than the caller's own budget, cancel the work when it expires, and surface the timeout as a distinct error.
- Circuit BreakerCount consecutive failures to a dependency, refuse calls while it looks broken, and let one probe test recovery - so a dead service cannot eat its callers.
- RetryRe-attempt only retryable, repeatable operations a bounded number of times, honour Retry-After, check cancellation between attempts, and surface the last error.
- Exponential BackoffSpace repeat attempts at base times two raised to the attempt, capped, with random jitter - so retries spread out instead of arriving in a synchronized herd.
- FallbackReturn a pre-decided lesser answer when a dependency cannot - stale cache, static default, partial result - so the journey continues, marked as degraded.
- Rate LimitingGive each client a refillable budget of calls - take a token to proceed, refuse with 429 and a Retry-After when the bucket is empty - so one client's burst cannot spend everyone's capacity.
Data Patterns
5 entriesPatterns for keeping application data honest at speed and across services: copies that exist only to be lost, multi-step transactions with explicit undos, and messages that cannot be lost or doubled.
- Cache-AsideRead through a cache: on a miss, load from the store and fill it; on a write, save to the store and evict the entry - so reads speed up while the store stays the only source of truth.
- Transactional OutboxWrite the outgoing message in the same transaction as the business change; a relay publishes and marks it sent - the commit and the message become one fact, not two hopes.
- SagaRun a multi-step transaction as local steps, each with a compensation; on failure, compensate the completed steps in reverse - consistency by explicit undo, not locks.
- Idempotent ConsumerRecord the ids of processed messages and skip ids already seen, so a redelivered webhook or queue event processes once no matter how many times it arrives.
- CQRSSplit the command model from per-view query models, joined by projections - each side shaped for its job, at the price of two models and eventual consistency.
Architecture Patterns
2 entriesPatterns for system boundaries and change over time: replace without stopping, and give each client a backend shaped for it - decisions measured in routes and releases, not classes.
- Strangler FigPut an interception layer in front of a legacy system and move routes to the replacement one at a time, until the old system has nothing left to serve and can be removed.
- Backends for FrontendsGive each frontend its own backend that aggregates and shapes the services it needs - so the web app, the mobile app, and any other client stop negotiating one API into serving them all.