fedorthinks

Express course · No. 04

Most of them you've already reinvented by hand. A pattern is just the name — so a team can say in one word what would take a paragraph, and recognise the move before building it badly.

20 patterns · a diagram for each · cheat sheet at the end

§ 01

A design pattern is a named, reusable solution to a problem that shows up again and again in code. It's vocabulary, not a library — you don't install it, you recognise it.

Design Pattern — a name for a move you already make

Footballers don't invent "the give-and-go" mid-match. It has a name, and saying the name is faster than describing the whole move.

A design pattern is a move competent developers reinvent by hand anyway. Naming it turns a paragraph of explanation into one word the whole team shares. When someone says "wrap it in a Decorator," everyone sees the shape instantly — and that is the entire point of a pattern: a shared vocabulary for moves you'd make regardless.

ConceptDesign Pattern
What it is
A named solution to a problem that keeps recurring in code.
What it isn't

Not a library: you don't install it, you recognise it and write it.

Scale

Lives inside the code of one module — unlike architectural patterns, which decide the floor plan of the whole system.

Why
Shared language: one word instead of a paragraph.

Gang of Four — patterns are discovered, not invented

Nobody invented the arch. Builders kept finding it was the strongest way to span a gap — so it got a name.

The Gang of Four (GoF) are the four authors of the book Design Patterns. They didn't design 23 clever tricks; they catalogued solutions that kept reappearing in good code. So a pattern isn't a target to hit — it's a shape you arrive at naturally when the problem calls for it. If you're forcing one in, you probably don't have the problem yet.

The map: three families, three questions

A kitchen has tools for three jobs: making the food, plating it, and serving it. The patterns split the same way.

Creational patterns are about how objects are born — who builds them, and how. Structural patterns are about how objects fit together into larger shapes. Behavioural patterns are about how objects talk and divide responsibility. Almost every classic pattern is one of those three answers.

Creationalhow objects are bornFactoryAbstract FactoryBuilderSingletonPrototypeStructuralhow objects fit togetherAdapterDecoratorFacadeProxyCompositeBehaviouralhow objects talk and share workStrategyObserverCommandChain of ResponsibilityStateIteratorTemplate MethodMediatorVisitorMemento
Three families and the course's 20 patterns — chapters 2–5 follow them.

Indirection — a pattern you don't need is just complexity

A Swiss Army knife in your pocket is handy. Bolting all twenty tools onto your front door is not.

Every pattern adds indirection — a layer between you and the thing. That's worth it when it buys flexibility you'll actually use, and pure cost when it doesn't. The common mistake isn't ignorance of patterns; it's reaching for one before the problem exists.

How to read each pattern

A passport: every one has the same fields, so they're easy to compare.

Every pattern from here on has the same parts: its English name (that's the term — remember it), a picture from everyday life, a diagram, and a card with fields: problem (what hurts), idea (how it solves it), example, cost (what you pay), when to use, and related patterns. At the end there's a cheat sheet with every name on one page.

A pattern is a shortcut for a conversation. Use it to be understood, not to look clever.

§ 02

How objects come to life — without scattering new everywhere and welding your code to concrete classes.

Factory — ask for a thing by name, not by recipe

A coffee machine: you press "latte" and get one. You don't grind, froth, and pour yourself — and you don't need to know how it's done.

A Factory hands you an object without you calling its constructor directly, so the calling code never depends on the concrete class. It only knows the interface. It buys the freedom to change what gets built without touching who asked for it.

Clientasks by namecreate("stripe")Factorypicks the classStripeProviderPayPalProviderFakeProviderthe caller knows only the PaymentProvider interface — never the concrete class
The client asks by name; the factory picks the class; the client only sees the PaymentProvider interface.
PatternFactory· Factory Method
Problem

new StripeProvider() is scattered through the code — welded to a class.

Idea
Ask a factory for the object; it decides which class to build.
Example

createPaymentProvider("stripe") returns a PaymentProvider. Switching to PayPal means changing the factory, not every call site.

Cost
An extra layer. A factory that builds exactly one thing is a smell.
When to use
There are several implementations, or there will be.
Related
Abstract Factory — the same idea for a whole family of objects.

Abstract Factory — a whole matching family at once

Buying a furniture set — "Victorian" or "Modern" — where every piece arrives in the same style, with no mismatched chairs.

When objects must come in consistent families, an Abstract Factory builds the whole set at once so the parts fit together. Powerful — but it's heavy machinery, worth it only when the families are real.

macOS factoryButtonmacMenumacDialogmacWindows factoryButtonwinMenuwinDialogwinpick ONE familyone factory = one matching set; never a mac Button next to a Windows Menu
One factory, one matching set: button, menu and dialog in the same style.
PatternAbstract Factory
Problem
Objects must match each other, and they're easy to mix up.
Idea
One factory produces the whole set in one style.
Example

A UI toolkit producing matching buttons, menus and dialogs for macOS or for Windows from one factory.

Cost
Heavy machinery: lots of interfaces and classes.
When to use
Only when the families are real, and there's more than one.
Related

Built from Factory. "An abstract factory for one product" is classic over-engineering.

Builder — assemble a complex object step by step

Ordering a custom burger — bun, patty, no onion, extra cheese — one choice at a time, then "done."

When an object has many optional parts, a Builder lets you set them piece by piece instead of a monstrous constructor with twelve arguments. At the end you call build() and get the finished object. It trades one baffling constructor for a readable chain.

set one optional part at a timeselect(name)where(age>18)limit(10)build()Queryready, valid objectnew Query(a, b, c, … 12 args)which argument is which?instead ofa readable chain replaces a monstrous constructor
A chain of steps → build() → a finished object. Instead of a constructor where you can't tell which argument is which.
PatternBuilder
Problem
A twelve-argument constructor, half of them optional.
Idea
Set the parts one at a time, then build().
Example

QueryBuilder().select("name").where("age > 18").limit(10).build().

Cost
One more class next to the real one.
When to use
The object has many optional parts.
Related

Factory decides what to build; Builder decides how to assemble something complex.

Singleton — exactly one, shared by all

A country has one president. Everyone who refers to "the president" means the same person — there aren't two.

A Singleton guarantees a single instance with one global access point. But handle with care: a singleton is global state in a nice coat, and global state makes testing and reasoning hard.

BillingAuthReportsAPIgetInstance()Configthe one instanceeveryone reaches the same global — handy, but hard to test
Every module reaches the same instance — handy, but it's global state.
PatternSingleton
Problem
You need exactly one shared instance.
Idea
The class itself guarantees one instance and one access point.
Example
A configuration object or logger everyone reads from.
Cost
Global state: testing and reasoning get harder.
When to use

Rarely. A single instance you pass in explicitly often beats one reached through a global.

Related
Creational like Factory, but about "how many", not "which one".

Prototype — copy a filled-in thing instead of building fresh

Photocopying a completed form is faster than filling a blank one from scratch.

When making an object from scratch is expensive or fiddly, a Prototype lets you clone an existing one and tweak it. Handy when objects are costly to construct and mostly similar.

Enemyconfigured: hp, skin, AIclone() + tweakcopy #1tweak: colourcopy #2tweak: speedcopy #3as ischeaper thanbuilding from zerocopy a filled-in object instead of rebuilding its setup
A configured object is cloned and lightly tweaked — instead of being built again.
PatternPrototype
Problem
Building the object from scratch is slow and fiddly.
Idea
Take a ready object, copy it, adjust the differences.
Example
Duplicating a configured game enemy, or a styled document node.
Cost
Copying needs care: what gets copied, and what stays shared.
When to use
Objects are costly to construct and mostly similar.
Related
An alternative to Factory: not "build", but "copy".

Hide the new. The fewer places that know how an object is built, the freer you are to change it.

§ 03

How objects compose into larger structures — fitting incompatible parts together and adding capability without a rewrite.

Adapter — a plug converter between two interfaces

Your laptop charger abroad — the device is fine, the socket is fine; you just need the little converter between them.

An Adapter wraps one interface so it looks like another, letting two things that weren't designed to cooperate work together. It's how you stop someone else's API from leaking into your whole codebase.

Your codeexpects your interfacepay()Adaptertranslates callscharge()Vendor SDKits own shapeyour code never sees the vendor's shape
Your code calls pay(); the adapter translates it into the vendor's charge().
PatternAdapter· wrapper
Problem

Someone else's interface doesn't match yours and spreads through your code.

Idea
A wrapper that translates calls from one interface to another.
Example

A third-party payment SDK wrapped so it satisfies your own PaymentProvider.

Cost
One more layer to update when the vendor's API changes.
When to use
Plugging in third-party or legacy code.
Related

Wraps an object like Decorator and Proxy, but changes the interface.

Decorator — add toppings without changing the pizza

A plain pizza, then cheese, then mushrooms — each layer wraps the last and adds something, and it's still a pizza.

A Decorator wraps an object to add behaviour without modifying the original or subclassing it. The interface stays the same, so layers stack. It lets you add features in combinations nobody had to anticipate.

Encrypt decoratorCompress decoratorFileStreamthe originalwrite()each layer wraps the last, adds one thing, keeps the same interface
A stream wrapped in compression, and that wrapped in encryption. From outside it's still a stream.
PatternDecorator· wrapper
Problem
You need add-ons in any combination; a subclass for each won't scale.
Idea
Wrap the object, add one behaviour, keep the interface.
Example

A data stream → compression → encryption; each layer can be stacked or removed.

Cost
Lots of small wrappers; a stack of layers is harder to debug.
When to use
Capabilities need to be combined at runtime.
Related

Same shape as Proxy, but the goal is to add, not to control. The textbook case of composition over inheritance.

Facade — one simple front desk over a messy back office

A hotel concierge — you say "I need a taxi and a dinner reservation," and they handle the tangle of phone calls behind the counter.

A Facade gives a simple, single entry point to a complicated subsystem, hiding its moving parts. It shrinks a big surface down to the one door most callers need.

ClientVideoConverterconvert(file, mp4)one doorfor most callerssubsystemCodecsBuffersAudio streams
One convert() call — with codecs, buffers and audio streams behind it.
PatternFacade
Problem
Doing one simple thing means knowing a dozen subsystem classes.
Idea
One simple door that orchestrates the subsystem.
Example

VideoConverter.convert(file, "mp4") quietly orchestrates codecs, buffers and audio streams.

Cost

The complexity doesn't vanish — it's hidden. Fine control still goes around the facade.

When to use
Most callers need one or two simple scenarios.
Related

Adapter changes the interface of one thing; Facade simplifies a whole subsystem.

Proxy — a stand-in that controls access

A celebrity's assistant — you don't reach the star directly; the assistant screens, schedules, and sometimes answers for them.

A Proxy stands in front of an object to control access to it — for lazy loading, permissions, caching, or talking to something remote. Same interface, an extra gate in front.

ClientProxysame interfaceonly if neededRealImageheavy, loaded latelazy load · access checkcache · remote call
The client talks to the proxy as if it were the real object; the proxy decides when — and whether — to pass the call on.
PatternProxy· stand-in
Problem

The object is expensive to load, needs permissions, or lives on another machine.

Idea
A stand-in with the same interface sits in front of the real object.
Example

An image proxy that doesn't load the real file until it's shown; an access proxy that checks permissions before forwarding the call.

Cost
An extra hop on every call; latency hidden from the caller.
When to use
Lazy loading, permissions, caching, remote objects.
Related
Same shape as Decorator, different goal — access control.

Composite — treat a tree and a leaf the same

A folder holds files and other folders. "Calculate the size" works the same whether you ask one file or the whole tree.

A Composite lets you treat a single object (a leaf) and a group of objects (a composite) uniformly — they share one interface. It turns recursive structures into something you handle without special-casing every level.

Folderfile.txtFolderphoto.jpga.mdb.mdgetSize() and render() work the same on one leaf and on a whole tree
A folder and a file answer the same calls — the tree is walked with no special cases.
PatternComposite· tree
Problem
Working with a tree needs a special case at every level.
Idea
Leaf and branch share one interface; a branch just calls its children.
Example

A UI where a button and a panel-full-of-buttons both answer render() and getSize().

Cost

The shared interface can be too general: not every operation makes sense on a leaf.

When to use
The data is naturally a tree: folders, UI, documents.
Related
Walked with Iterator; new operations are added with Visitor.

Composition over inheritance: snap behaviour together at runtime instead of freezing it into a class tree.

§ 04

The first half of the behavioural patterns: how objects share work and talk to each other — so responsibility is split cleanly and the right code runs at the right moment.

Strategy — swap the algorithm, keep the caller

A maps app: same trip, but you pick "fastest," "shortest," or "avoid tolls," and it routes differently. You choose the strategy; the app just follows it.

A Strategy makes an algorithm interchangeable at runtime, so the caller stays the same while the method varies. In modern languages this is often just passing a function rather than a whole class — which is the point: the pattern is the idea, not the ceremony.

Checkoutuses a strategyPricingStrategyinterface / functionRegularMemberHolidaySaleswap the algorithm at runtime; the caller never changes
Checkout calls a PricingStrategy; which pricing it gets is decided at runtime.
PatternStrategy
Problem
A growing if ladder over variants of one algorithm.
Idea
The algorithm is a swappable object (or function) behind one interface.
Example

A checkout that takes a PricingStrategy: regular, member, or holiday-sale.

Cost
A Strategy for one algorithm that never varies is dead weight.
When to use
Two or more variants, chosen at runtime.
Related
Same shape as State. In modern code, often just a function.

Observer — subscribe, and get told when it changes

A newsletter — you subscribe once, and every new issue comes to you. The publisher doesn't phone each reader; it just sends to the list.

With an Observer, subscribers register with a subject and get notified when it changes — without the subject knowing who they are. It's the backbone of event-driven and reactive code.

notify()Subjectspreadsheet cellChartPivot tableSummarythe subject keeps a list of subscribers — it doesn't know who they are
The cell changes → notify() → every dependent chart and table updates itself.
PatternObserver· pub/sub
Problem

An object must tell many others about a change without knowing them by name.

Idea
A list of subscribers + notify() on every change.
Example

A spreadsheet cell refreshing every chart that depends on it; UI frameworks reacting to state; pub/sub everywhere.

Cost

Notification chains are hard to trace; a forgotten subscription lives forever.

When to use
Several independent parts react to one change.
Related

The basis of event-driven code — the same as Event-driven architecture, inside one program.

Command — wrap a request as an object

A restaurant order ticket — the request "table 5, two coffees" becomes a slip you can queue, reorder, log, and even tear up.

A Command turns an action into a standalone object, so you can queue it, log it, schedule it, or undo it. It's how an action becomes something you can store and replay.

Editoruser actioncommand historyTypeTextdo() · undo()Bolddo() · undo()Deletedo() · undo()executeDocumentreceiveran action becomes an object: queue it, log it, undo it, replay it
Every edit is an object with do() and undo(); the command history gives undo/redo and macros.
PatternCommand
Problem
An action needs to be delayed, repeated, logged, or undone.
Idea
Pack the action into an object with everything needed to run it.
Example

Every edit in an editor is a command — hence undo/redo and macros. A job queue is commands waiting their turn.

Cost
An object per action; undo has to be thought through for each command.
When to use
Undo/redo, queues, macros, an action log.
Related
Often paired with Memento for undo.

Chain of Responsibility — pass it along until someone handles it

Customer support tiers — the front desk tries, escalates to a specialist, then to a manager, until someone can actually solve it.

With a Chain of Responsibility, a request travels along a chain of handlers; each either deals with it or passes it on. It decouples the sender from whoever ends up doing the work.

middleware chainRequestAuthLoggingRate limitRoutehandles it401, stopeach link handles its part — or passes the request on
Web middleware: auth → logging → rate limit → route. Any link can stop the request.
PatternChain of Responsibility· middleware
Problem
The sender shouldn't know who exactly will handle the request.
Idea
A chain of handlers: each does its part or passes it on.
Example

Web middleware: auth, then logging, then rate-limiting, then the route itself.

Cost
The order of links matters; a request can run the whole chain unhandled.
When to use
Several independent checks or steps before the main work.
Related
On the web you almost always meet it as middleware.

Good behavioural patterns let two pieces cooperate without either one hard-wiring the other in.

§ 05

The second half of the behavioural patterns: how an object's behaviour changes with its state, how you step through collections, and how you fix a skeleton while leaving one step open.

State — behaviour that changes with the mode you're in

A traffic light — green, yellow, red — where each colour decides what happens now and which colour comes next. Same light, different behaviour per state.

The State pattern lets an object change its behaviour as its internal state changes. A tangle of if and switch becomes clear states and transitions — a small state machine. It turns a mess of flags into a tidy little machine.

pendingpaidshippedcancelledpay()ship()cancel()cancel()each state knows only its own rules and what it can become
An order: pending → paid → shipped; it can only be cancelled from pending or paid.
PatternState· state machine
Problem

Behaviour depends on a mode, and the code fills up with flags and switch.

Idea
Each state is its own object with its own rules and transitions.
Example

An order that behaves differently as pending, paid, shipped or cancelled; each state knows only its own rules and what it can become.

Cost
Lots of small classes; for two states a plain if is enough.
When to use
Many states, and the transitions between them matter.
Related

Same shape as Strategy, but the object switches state itself as it lives.

Iterator — step through a collection without seeing its insides

A TV remote's next and previous — you move through channels without knowing how they're stored.

An Iterator gives a uniform way to walk a collection without exposing how it's built — array, tree, or linked list. This one is so useful the language usually has it built in — for..of, generators, __iter__. It's the clearest sign a pattern can graduate into a language feature.

ArrayTreeLinked listIteratornext() · hasNext()for..of loopsame code for allwalk any collection without seeing how it is stored
Array, tree and list all hand out the same next() — the loop doesn't know what's inside.
PatternIterator
Problem
Traversal code depends on how the collection is built.
Idea
One way to get "the next element", whatever is inside.
Example

for (item of collection) works the same over a list or a custom structure.

Cost
Close to zero — it's usually built into the language already.
When to use
Always — but through the built-in tools, not by hand.
Related
Walks the trees built with Composite.

Template Method — a fixed recipe with one blank to fill

A recipe that's identical every time — except "add your choice of spice" at step four. The skeleton is fixed; one step is yours.

A Template Method defines the skeleton of an operation in a base class and lets specific steps be overridden without changing the overall shape. Useful when many flows share a shape but differ in a spot or two.

fixed skeleton in the base classopen()read()parse()you fill this insave()CSV parseJSON parsesubclasses supplyonly this one step
A base importer opens, reads, parses and saves; subclasses supply only the parse step.
PatternTemplate Method
Problem
Several flows of the same shape copy each other almost entirely.
Idea

The skeleton lives in a base class; the varying steps live in subclasses.

Example

An importer that opens, reads, parses (you fill this in), and saves; CSV and JSON importers supply only the parse step.

Cost
It relies on inheritance; the skeleton is hard to change later.
When to use
The shape is shared, the differences sit in one or two spots.
Related

Strategy solves a similar problem with composition instead of inheritance.

Mediator, Visitor, Memento — the rest, in one breath

A toolbox has tools you reach for monthly, not daily — but you should still know they exist.

A handful more earn their place occasionally. Mediator — a control tower so objects talk through one hub instead of a tangle of direct links. Visitor — add new operations to a structure without editing its classes. Memento — capture an object's state so you can restore it later. Know the names; reach for them only when the exact problem appears.

MediatorVisitorMementoABCDHubone hub, not a tangleCircleSquareTextExportVisitornew operationclasses stay untouchedEditorSnapshotsaved statesaverestoreundo · save points
Mediator: everything through a hub. Visitor: a new operation walks the classes from outside. Memento: snapshot and restore.
PatternMediator
What it is

One hub objects talk through instead of linking to each other directly.

Picture
A control tower: planes talk to it, not to each other.
When to use
Direct links between objects have become too many.
PatternVisitor
What it is
A new operation over a structure, moved into its own object.
Example

Exporting every shape in a document — without editing the shape classes.

When to use
The structure is stable, but operations on it keep multiplying.
PatternMemento· snapshot
What it is
A saved state of an object you can go back to.
Example
Save points in a game, undo snapshots in an editor.
Related
Together with Command it gives you undo.

When a pattern becomes a language keyword, stop writing the pattern and use the keyword.

§ 06

The catalogue is decades of hard-won wisdom — and also a product of its time. Use it like a senior engineer, not a checklist.

Language features — many patterns are now built in

We used to give directions by landmarks; now the phone navigates. The skill didn't vanish — it got absorbed into the tool.

Iterator is for..of. Strategy is often a function passed in. Decorator and Observer are first-class in modern frameworks. When the language hands you the shape for free, writing the full pattern by hand is just ceremony (boilerplate). The idea still matters; the boilerplate usually doesn't.

the patternwhat the language gives you nowIteratorfor..of · generators · __iter__Strategya function passed inDecoratorbuilt into frameworksObserverreactive state in UI frameworks
On the left, the catalogue pattern; on the right, what the language or framework already gives you instead.

Pattern-itis — a real disease

A cook who empties the whole spice rack into one dish doesn't get a richer meal — they get an inedible one.

Pattern-itis is the classic over-engineering smell: reaching for patterns to look sophisticated. And it's worse now — an AI assistant will happily generate a "Multi-Level Abstract Factory" for what should be three lines. Simpler code is almost always the more senior choice.

Anti-patternPattern-itis· over-engineering
What it is
Patterns for their own sake, not to relieve a pain.
Symptoms

An abstract factory for one product, a Strategy for one algorithm that never varies, five layers of indirection around an if.

Why it's worse now
AI assistants generate these structures eagerly and fast.
Cure
Simplest code first; a pattern only once the pain shows up.

Patterns are a vocabulary, not a law

Knowing many words doesn't make a good writer. Knowing which word — and when to stay silent — does.

The real value of the catalogue is shared language: "let's put a Facade here" lands instantly with anyone who knows the term, and that is worth a lot on a team. But the goal is always the simplest code that solves the problem. The pattern is a means; naming one is never the achievement.

Learn all the patterns so you can recognise them. Use as few as you can get away with.

§ 07

Patterns are answers. The skill is matching them to a real question — and knowing when no pattern is the right answer.

Let the pattern emerge from the pain

You don't pick a wrench before you've found the bolt. You see the problem, then reach for the tool that fits it.

Good pattern use is usually a refactoring, not a starting blueprint: you write the simple thing, feel a specific pain — this if ladder keeps growing, this class knows too much about how it's built — and then the pattern that relieves it is obvious. Forcing patterns up front is how you build cathedrals nobody asked for.

Name it only when the name helps

You don't say "I performed a give-and-go" in casual chat. But on the pitch, with teammates, the word saves a whole sentence.

A pattern's payoff is communication and flexibility. If naming it makes the code clearer to the next person, use the name out loud — in a class name, a comment, a design chat. If the indirection buys nothing, the plainest code wins, pattern or not.

Patterns are connected

Words in a language don't live alone: they have synonyms, pairs and relatives.

Adapter, Decorator and Proxy are one shape: a wrapper around an object, with different goals. Strategy and State are alike in shape. Command and Memento together give you undo. Abstract Factory is built from Factory. Composite is walked with Iterator. Observer is the backbone of event-driven code.

all wrap one objectAdapterchanges the interfaceDecoratoradds behaviourProxycontrols accessStrategyStatesame shapeCommandMementoundoAbstract FactoryFactoryusesCompositeIteratorwalk the treeObserverEvent-driven codebackbone ofChain of Responsibility= web middleware
The main links between the course's patterns.
Before reaching for a pattern
  • What recurring problem does it solve? Say it in a sentence.
  • Do I have that problem now, or am I guessing at the future?
  • Would a plain function or object do? Try that first.
  • Does my language already give me this for free?
  • Will naming it make the code clearer to the next person — or just fancier?
  • Am I refactoring toward it, or forcing it in up front?
Smell tests that you over-engineered
  • You have a factory that builds exactly one thing.
  • A Strategy with a single strategy that never changes.
  • More interfaces and indirection than actual behaviour.
  • You added the pattern to look senior, not to solve a pain.
  • A new reader needs a UML diagram to follow three lines of logic.
Signs you chose well
  • The pattern removed an if/switch ladder that kept growing.
  • You can swap an implementation without touching the callers.
  • A teammate recognised the shape from its name immediately.
  • The indirection earns its keep — you actually use the flexibility.
  • The code is simpler with the pattern than without it, not just cleverer.

Cheat sheet: all 20 patterns and the key ideas

Foundations

Design Pattern

A named solution to a recurring problem in code. Vocabulary, not a library.

Gang of FourGoF

The authors of Design Patterns, who catalogued 23 patterns.

Indirection

A layer between you and the thing. The cost of every pattern.

Pattern-itisover-engineering

Patterns for show, not for pain. Simple code almost always wins.

Creational

FactoryFactory Method

Ask for an object by name; the factory picks the class.

Abstract Factory

A factory for a whole matching family of objects.

Builder

A complex object step by step, then build().

Singleton

Exactly one instance for everyone. Careful: global state.

Prototype
Clone a ready object and tweak it.

Structural

Adapter

A converter: one interface looks like another.

Decorator

A wrapper adds behaviour; the interface stays the same.

Facade
One simple door into a complex subsystem.
Proxy

Stands in front of an object and controls access.

Composite
A leaf and a tree share one interface.

Behavioural: talking

Strategy

A swappable algorithm; often just a function.

Observer
Subscribers get told about changes.
Command
An action as an object: queue, log, undo.
Chain of Responsibilitymiddleware

Handlers in a chain; on the web, middleware.

Behavioural: state and steps

State
Each state has its own rules and transitions.
Iterator

Walk a collection without looking inside. Usually for..of.

Template Method

The skeleton is fixed; one step is yours.

Mediator
Everyone talks through one hub.
Visitor
A new operation without editing the classes.
Memento
Save a state and come back to it.

The best use of a design pattern is the one a reader never notices — because it made the code feel obvious.

End of express course · 7 chapters · 20 patterns

Next comes the source: the Gang of Four's Design Patterns, and its kinder modern companions — Head First Design Patterns, refactoring.guru, Martin Fowler's Refactoring. But read them the way you'd learn chess openings: not to memorise moves, but to recognise the position when it appears on your own board.