Generated by
scripts/build_catalog.py. Do not edit by hand.
Every pattern below is used by at least one problem in this repository, in code you can run. Each entry says what the pattern is for, the question in a problem that makes you reach for it, and the mistake it tends to attract — then lists where to go and read one.
20 patterns across 17 problems.
Create families of related objects whose members have to be consistent with each other.
Reach for it when: Do these objects only make sense together — and would mixing two families be a bug rather than a style choice?
The usual mistake: Reaching for it when one product would do. If the members do not have to agree, a Factory Method is the smaller answer.
Worked examples:
- Design a Payment Gateway (🔴 Hard) — alongside Adapter, Strategy, Facade
Wrap three payment SDKs that disagree about units, method names and how failure is signalled behind one interface, then use an abstract factory so a region's processor, tax rules and money formatting can never be mixed up.
Make an interface you do not control fit one you do.
Reach for it when: Am I wrapping something I cannot change — a vendor SDK, a legacy class, a protocol?
The usual mistake: Letting the foreign interface leak through anyway — a vendor exception type escaping, or an amount crossing the boundary in the wrong units.
Worked examples:
- Design a Payment Gateway (🔴 Hard) — alongside Abstract Factory, Strategy, Facade
Wrap three payment SDKs that disagree about units, method names and how failure is signalled behind one interface, then use an abstract factory so a region's processor, tax rules and money formatting can never be mixed up.
Assemble an object across several steps, validating only once it is complete.
Reach for it when: Does this object need many pieces, several optional, arriving at different moments?
The usual mistake: Using it for three arguments. A constructor is fine until half-built objects start escaping in an invalid state.
Worked examples:
- Design a Movie Ticket Booking System (🔴 Hard) — alongside Repository, Proxy, Strategy, Facade
Stop two people buying the same seat by holding it under an expiring lock taken before payment and released after, with a builder assembling the booking, a repository hiding where shows live, and a caching proxy in front of it.
Pass a request along a chain of handlers until one of them deals with it.
Reach for it when: Could any of several handlers deal with this, and should the sender not have to know which?
The usual mistake: Copying the pattern without asking whether the chain should stop. For logging it must not; for an approval workflow it must.
Worked examples:
- Design a Logging Framework (🟡 Medium) — alongside Strategy, Singleton
Route log records down a handler chain where every link applies its own threshold and format, so one chain can send everything to the console and only errors to a JSON file — and where the chain deliberately does not stop at the first handler that takes it. - Design an ATM (🟡 Medium) — alongside State
Model an ATM as a state machine where each state permits only what is safe from it, and build the note dispenser as a chain of denomination handlers that plans the full amount before a single note leaves the box.
Turn an operation into an object, so it can be queued, logged, or undone.
Reach for it when: Do I need undo, a replayable history, or a way to defer this action?
The usual mistake: Storing too little to invert the operation, or capturing that data at construction rather than at execution.
Worked examples:
- Design a Parking Lot (🟡 Medium) — alongside Strategy, Factory Method, Facade
Assign spots to arriving vehicles by a pluggable allocation strategy, charge for the stay on exit by a separate pricing strategy, and drive the whole thing from a command console where adding an operation never edits an existing one. - Design a Text Editor with Undo (🟡 Medium) — alongside Memento, Composite, Facade
Build an editor whose every edit is a reversible command, where consecutive keystrokes coalesce into one undo step, replace-all undoes as a single action, and a new edit after an undo correctly discards the redo stack. - Design Chess (🔴 Hard) — alongside Strategy, Template Method, Observer
Give each piece responsibility for how it moves, make every move an undoable command, and decide legality by playing a move and asking whether your own king is now attacked — verified against known perft counts to depth four.
Treat a single object and a group of objects through the same interface.
Reach for it when: Is this a tree where a container should be usable wherever a leaf is?
The usual mistake: Two typed child lists instead of one. Every traversal then gets written twice, and the copies drift.
Worked examples:
- Design a Text Editor with Undo (🟡 Medium) — alongside Command, Memento, Facade
Build an editor whose every edit is a reversible command, where consecutive keystrokes coalesce into one undo step, replace-all undoes as a single action, and a new edit after an undo correctly discards the redo stack. - Design an In-Memory File System (🟡 Medium) — alongside Visitor, Iterator, Facade
Model files and directories as one composite tree so no caller ever branches on which it is holding, then add search, disk usage and rendering as visitors that walk the tree without living on it.
Add behaviour around an object without changing it, by wrapping it in something of the same type.
Reach for it when: Does this behaviour apply to several implementations, and should it compose with other such behaviour?
The usual mistake: Forgetting that stacking order changes the result, and not deciding deliberately which order you want.
Worked examples:
- Design a Notification Service (🟡 Medium) — alongside Observer, Factory Method, Strategy
Fan a message out to email, SMS, push and Slack according to each subscriber's per-channel priority threshold, with retry, rate limiting and deduplication written once as decorators that compose around any channel.
Offer one simple entry point onto a subsystem that has several parts.
Reach for it when: Does a caller who wants one common thing have to know about four objects to get it?
The usual mistake: Turning it into a god object. A facade delegates; it does not accumulate the logic itself.
Worked examples:
- Design a Chat Room (🟡 Medium) — alongside Mediator, Observer
Route messages through rooms so participants never hold references to each other, turning N-squared peer coupling into N — and put blocking, muting and moderation in the mediator, since each is a rule about a relationship neither party should own. - Design a Movie Ticket Booking System (🔴 Hard) — alongside Builder, Repository, Proxy, Strategy
Stop two people buying the same seat by holding it under an expiring lock taken before payment and released after, with a builder assembling the booking, a repository hiding where shows live, and a caching proxy in front of it. - Design a Parking Lot (🟡 Medium) — alongside Strategy, Factory Method, Command
Assign spots to arriving vehicles by a pluggable allocation strategy, charge for the stay on exit by a separate pricing strategy, and drive the whole thing from a command console where adding an operation never edits an existing one. - Design a Payment Gateway (🔴 Hard) — alongside Adapter, Abstract Factory, Strategy
Wrap three payment SDKs that disagree about units, method names and how failure is signalled behind one interface, then use an abstract factory so a region's processor, tax rules and money formatting can never be mixed up. - Design a Text Editor with Undo (🟡 Medium) — alongside Command, Memento, Composite
Build an editor whose every edit is a reversible command, where consecutive keystrokes coalesce into one undo step, replace-all undoes as a single action, and a new edit after an undo correctly discards the redo stack. - Design an In-Memory File System (🟡 Medium) — alongside Composite, Visitor, Iterator
Model files and directories as one composite tree so no caller ever branches on which it is holding, then add search, disk usage and rendering as visitors that walk the tree without living on it.
Decide which concrete class to create in one place, so callers never name it.
Reach for it when: Is the choice of implementation a decision I want made once rather than at every call site?
The usual mistake: A factory that is only ever called with one argument — that is a constructor with extra steps.
Worked examples:
- Design a Notification Service (🟡 Medium) — alongside Decorator, Observer, Strategy
Fan a message out to email, SMS, push and Slack according to each subscriber's per-channel priority threshold, with retry, rate limiting and deduplication written once as decorators that compose around any channel. - Design a Parking Lot (🟡 Medium) — alongside Strategy, Command, Facade
Assign spots to arriving vehicles by a pluggable allocation strategy, charge for the stay on exit by a separate pricing strategy, and drive the whole thing from a command console where adding an operation never edits an existing one.
Walk a collection without exposing how it is stored.
Reach for it when: Should callers be able to traverse this without knowing it is a dict, a tree, or a generator?
The usual mistake: Materialising the whole collection when a generator would let the caller stop early.
Worked examples:
- Design an In-Memory File System (🟡 Medium) — alongside Composite, Visitor, Facade
Model files and directories as one composite tree so no caller ever branches on which it is holding, then add search, disk usage and rendering as visitors that walk the tree without living on it.
Route interaction between many objects through one coordinator, so they do not reference each other.
Reach for it when: Would every participant otherwise hold a reference to every other, and who enforces the rules between two of them?
The usual mistake: Confusing it with Observer. A mediator has routing logic; a subject just notifies.
Worked examples:
- Design a Chat Room (🟡 Medium) — alongside Observer, Facade
Route messages through rooms so participants never hold references to each other, turning N-squared peer coupling into N — and put blocking, muting and moderation in the mediator, since each is a rule about a relationship neither party should own.
Capture an object's state so it can be restored later, without exposing its internals.
Reach for it when: Do I need to put something back exactly as it was, and is the state small enough to copy?
The usual mistake: Snapshotting something large on every change, and handing out a mutable snapshot that can be edited after the fact.
Worked examples:
- Design a Text Editor with Undo (🟡 Medium) — alongside Command, Composite, Facade
Build an editor whose every edit is a reversible command, where consecutive keystrokes coalesce into one undo step, replace-all undoes as a single action, and a new edit after an undo correctly discards the redo stack.
Let interested parties subscribe to events without the source knowing who they are.
Reach for it when: Should adding a new listener be registration rather than a code change at the source?
The usual mistake: Using it where a mediator is needed — as soon as the source starts deciding who gets what, it is no longer an observer.
Worked examples:
- Design a Chat Room (🟡 Medium) — alongside Mediator, Facade
Route messages through rooms so participants never hold references to each other, turning N-squared peer coupling into N — and put blocking, muting and moderation in the mediator, since each is a rule about a relationship neither party should own. - Design a Notification Service (🟡 Medium) — alongside Decorator, Factory Method, Strategy
Fan a message out to email, SMS, push and Slack according to each subscriber's per-channel priority threshold, with retry, rate limiting and deduplication written once as decorators that compose around any channel. - Design an Elevator System (🔴 Hard) — alongside Strategy, State
Run a bank of elevators where each car follows the LOOK algorithm — sweep one way serving every stop, reverse only when nothing is ahead — and the choice of which car answers a hall call is a strategy that can be tuned without any car noticing. - Design Chess (🔴 Hard) — alongside Strategy, Command, Template Method
Give each piece responsibility for how it moves, make every move an undoable command, and decide legality by playing a move and asking whether your own king is now attacked — verified against known perft counts to depth four. - Design Splitwise (🟡 Medium) — alongside Strategy
Track shared expenses across four split types where every split sums exactly to the total, keep one net balance per person instead of a debt matrix, and settle the whole group in at most n-1 payments. - Design Tic Tac Toe (🟢 Easy) — alongside Strategy
Play on an N x N board with O(1) win detection using per-line counters instead of scanning, and a bot whose difficulty is a swappable strategy — random, or a minimax player that provably never loses.
Stand in for another object with the same interface, controlling access to it.
Reach for it when: Do I need caching, lazy loading, access control or logging without the caller noticing?
The usual mistake: Caching reads and forgetting to invalidate on write, which is worse than no proxy because it is confidently wrong.
Worked examples:
- Design a Movie Ticket Booking System (🔴 Hard) — alongside Builder, Repository, Strategy, Facade
Stop two people buying the same seat by holding it under an expiring lock taken before payment and released after, with a builder assembling the booking, a repository hiding where shows live, and a caching proxy in front of it.
Hide where data lives behind a collection-shaped interface.
Reach for it when: Should the rest of the system care whether this comes from memory, a database, or an API?
The usual mistake: Letting query details leak through the interface, so swapping the backing store is no longer possible.
Worked examples:
- Design a Movie Ticket Booking System (🔴 Hard) — alongside Builder, Proxy, Strategy, Facade
Stop two people buying the same seat by holding it under an expiring lock taken before payment and released after, with a builder assembling the booking, a repository hiding where shows live, and a caching proxy in front of it.
Guarantee exactly one instance of something genuinely global.
Reach for it when: Would two of these be an actual bug, not just wasteful?
The usual mistake: Using it as a global variable. It is almost always the wrong answer, and it always costs testability — provide a reset.
Worked examples:
- Design a Logging Framework (🟡 Medium) — alongside Chain of Responsibility, Strategy
Route log records down a handler chain where every link applies its own threshold and format, so one chain can send everything to the console and only errors to a JSON file — and where the chain deliberately does not stop at the first handler that takes it.
Put behaviour in an object representing the current state, so transitions replace conditionals.
Reach for it when: Does the same method need to do something different — or be refused — depending on a mode?
The usual mistake: Keeping the state as a flag checked at the top of every method, so adding a state means revisiting all of them.
Worked examples:
- Design a Vending Machine (🟡 Medium)
Model a vending machine as an explicit state machine where each state decides which actions it accepts, and where a machine that cannot make change leaves the item on the shelf and the buyer's money untouched. - Design an ATM (🟡 Medium) — alongside Chain of Responsibility
Model an ATM as a state machine where each state permits only what is safe from it, and build the note dispenser as a chain of denomination handlers that plans the full amount before a single note leaves the box. - Design an Elevator System (🔴 Hard) — alongside Strategy, Observer
Run a bank of elevators where each car follows the LOOK algorithm — sweep one way serving every stop, reverse only when nothing is ahead — and the choice of which car answers a hall call is a strategy that can be tuned without any car noticing.
Make an algorithm swappable behind a common interface.
Reach for it when: Is there more than one reasonable way to do this, chosen by configuration rather than by the code?
The usual mistake: An if/else re-evaluated on every call. Real Strategy is chosen once and injected.
Worked examples:
- Design a Logging Framework (🟡 Medium) — alongside Chain of Responsibility, Singleton
Route log records down a handler chain where every link applies its own threshold and format, so one chain can send everything to the console and only errors to a JSON file — and where the chain deliberately does not stop at the first handler that takes it. - Design a Movie Ticket Booking System (🔴 Hard) — alongside Builder, Repository, Proxy, Facade
Stop two people buying the same seat by holding it under an expiring lock taken before payment and released after, with a builder assembling the booking, a repository hiding where shows live, and a caching proxy in front of it. - Design a Notification Service (🟡 Medium) — alongside Decorator, Observer, Factory Method
Fan a message out to email, SMS, push and Slack according to each subscriber's per-channel priority threshold, with retry, rate limiting and deduplication written once as decorators that compose around any channel. - Design a Parking Lot (🟡 Medium) — alongside Factory Method, Command, Facade
Assign spots to arriving vehicles by a pluggable allocation strategy, charge for the stay on exit by a separate pricing strategy, and drive the whole thing from a command console where adding an operation never edits an existing one. - Design a Payment Gateway (🔴 Hard) — alongside Adapter, Abstract Factory, Facade
Wrap three payment SDKs that disagree about units, method names and how failure is signalled behind one interface, then use an abstract factory so a region's processor, tax rules and money formatting can never be mixed up. - Design a Rate Limiter (🟡 Medium)
Implement token bucket, fixed window, sliding window log and sliding window counter behind one interface, and be able to say what each one gets wrong — starting with the boundary burst that lets a fixed window pass double its limit. - Design an Elevator System (🔴 Hard) — alongside State, Observer
Run a bank of elevators where each car follows the LOOK algorithm — sweep one way serving every stop, reverse only when nothing is ahead — and the choice of which car answers a hall call is a strategy that can be tuned without any car noticing. - Design an LRU Cache (🟡 Medium) — alongside Template Method
Build a fixed-capacity cache with O(1) get and put, backed by a hand-written doubly linked list, whose eviction rule swaps between LRU, LFU and FIFO without the cache learning what any of them mean. - Design Chess (🔴 Hard) — alongside Command, Template Method, Observer
Give each piece responsibility for how it moves, make every move an undoable command, and decide legality by playing a move and asking whether your own king is now attacked — verified against known perft counts to depth four. - Design Splitwise (🟡 Medium) — alongside Observer
Track shared expenses across four split types where every split sums exactly to the total, keep one net balance per person instead of a debt matrix, and settle the whole group in at most n-1 payments. - Design Tic Tac Toe (🟢 Easy) — alongside Observer
Play on an N x N board with O(1) win detection using per-line counters instead of scanning, and a bot whose difficulty is a swappable strategy — random, or a minimax player that provably never loses. - Snake and Ladder (🟢 Easy)
Build a turn-based Snake and Ladder game where the die can be swapped between fair and crooked without touching the game loop, and the board refuses layouts where one jump chains into another.
Fix the shape of an algorithm in a base class and let subclasses fill in the steps.
Reach for it when: Do several implementations share a skeleton and differ only in a few steps?
The usual mistake: Reaching for inheritance when the variation is data, not behaviour — if the subclasses differ only in the values they set, those are constructor arguments.
Worked examples:
- Design an LRU Cache (🟡 Medium) — alongside Strategy
Build a fixed-capacity cache with O(1) get and put, backed by a hand-written doubly linked list, whose eviction rule swaps between LRU, LFU and FIFO without the cache learning what any of them mean. - Design Chess (🔴 Hard) — alongside Strategy, Command, Observer
Give each piece responsibility for how it moves, make every move an undoable command, and decide legality by playing a move and asking whether your own king is now attacked — verified against known perft counts to depth four.
Add operations over a structure without putting them on the structure's classes.
Reach for it when: Do operations keep arriving while the set of node types stays fixed?
The usual mistake: Using it where new node types are the common change — then every visitor has to grow a method, and you have made the expensive case the frequent one.
Worked examples:
- Design an In-Memory File System (🟡 Medium) — alongside Composite, Iterator, Facade
Model files and directories as one composite tree so no caller ever branches on which it is holding, then add search, disk usage and rendering as visitors that walk the tree without living on it.