# Design patterns are a shared vocabulary

Express course on the classic design patterns. 20 patterns from the Gang of Four catalogue — Factory, Builder, Adapter, Decorator, Strategy, Observer, State and more — each with its English name, a diagram, a problem → idea → example → cost card, and its links to neighbours. A one-page cheat sheet of every pattern at the end.

- **Author:** Fedor Chishchin
- **Level:** intro
- **Reading time:** ~30 minute read
- **Published:** 2026-06-02
- **Source:** https://fedorthinks.com/learn/design-patterns-express

---

## 1. What a pattern is

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.

#### Design 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.

_Diagram: 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.

> **Before naming a pattern:** "Do I have the recurring problem this solves — or do I just like the word?"

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

## 2. Creational patterns

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.**

_Diagram: The client asks by name; the factory picks the class; the client only sees the PaymentProvider interface._

#### Factory (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.

_Diagram: One factory, one matching set: button, menu and dialog in the same style._

#### Abstract 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.**

_Diagram: A chain of steps → build() → a finished object. Instead of a constructor where you can't tell which argument is which._

#### Builder

- **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.

_Diagram: Every module reaches the same instance — handy, but it's global state._

#### Singleton

- **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.

_Diagram: A configured object is cloned and lightly tweaked — instead of being built again._

#### Prototype

- **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".

> **The creational question:** "Who decides which concrete class gets built — and how hard is it to change that decision?"

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

## 3. Structural patterns

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.**

_Diagram: Your code calls pay(); the adapter translates it into the vendor's charge()._

#### Adapter (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.**

_Diagram: A stream wrapped in compression, and that wrapped in encryption. From outside it's still a stream._

#### Decorator (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.**

_Diagram: One convert() call — with codecs, buffers and audio streams behind it._

#### Facade

- **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.

_Diagram: The client talks to the proxy as if it were the real object; the proxy decides when — and whether — to pass the call on._

#### Proxy (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.**

_Diagram: A folder and a file answer the same calls — the tree is walked with no special cases._

#### Composite (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**.

> **The structural question:** "Am I changing what an object does — or just how it's wrapped and reached?"

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

## 4. Talking and sharing work

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.

_Diagram: Checkout calls a PricingStrategy; which pricing it gets is decided at runtime._

#### Strategy

- **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.**

_Diagram: The cell changes → notify() → every dependent chart and table updates itself._

#### Observer (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.**

_Diagram: Every edit is an object with do() and undo(); the command history gives undo/redo and macros._

#### Command

- **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.**

_Diagram: Web middleware: auth → logging → rate limit → route. Any link can stop the request._

#### Chain 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**.

> **The collaboration question:** "Could I change who handles this, or how, without the caller noticing?"

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

## 5. State, steps, traversal

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.**

_Diagram: An order: pending → paid → shipped; it can only be cancelled from pending or paid._

#### State (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.

_Diagram: Array, tree and list all hand out the same next() — the loop doesn't know what's inside._

#### Iterator

- **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.

_Diagram: A base importer opens, reads, parses and saves; subclasses supply only the parse step._

#### Template 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.

_Diagram: Mediator: everything through a hub. Visitor: a new operation walks the classes from outside. Memento: snapshot and restore._

#### Mediator

- **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.

#### Visitor

- **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.

#### Memento (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.

> **The control question:** "Is this forest of `if`s secretly a State machine or a Strategy?"

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

## 6. The modern view

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.

_Diagram: 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.

#### Pattern-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.

> **The modern test:** "Would simpler code — a function, a plain object, a language feature — do this just as well?"

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

## 7. Choosing well

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.

_Diagram: 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 Four** (GoF): The authors of _Design Patterns_, who catalogued 23 patterns.
- **Indirection**: A layer between you and the thing. The cost of every pattern.
- **Pattern-itis** (over-engineering): Patterns for show, not for pain. Simple code almost always wins.

### Creational

- **Factory** (Factory 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 Responsibility** (middleware): 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.
