Intro
Design patterns are reusable solutions to common software design problems. Vocabulary for code reviews, blueprints for tricky relationships.
Design patterns — what they are
EXAMPLE
// ===== The classic categories (Gang of Four) =====
// Creational: Factory, Abstract Factory, Builder, Prototype, Singleton
// Structural: Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
// Behavioural: Chain of Resp, Command, Iterator, Mediator, Memento, Observer,
// State, Strategy, Template Method, Visitor
// ===== Modern additions =====
// Repository, Unit of Work, Dependency Injection, Specification, CQRS,
// Event Sourcing, Saga, Hexagonal Architecture, Clean / Onion Architecture
// ===== Worked example: Strategy =====
class Pricer { price(o) { throw new Error('abstract'); } }
class RetailPricer extends Pricer { price(o) { return o.subtotal; } }
class WholesalePricer extends Pricer { price(o) { return o.subtotal * 0.9; } }
function quote(order, pricer) { return pricer.price(order); }
// Adding a new tier? Add a new class. Don't touch existing ones.
// ===== Worked example: Observer =====
class EventBus {
constructor() { this.handlers = new Map(); }
on(evt, h) { (this.handlers.get(evt) ?? this.handlers.set(evt, []).get(evt)).push(h); }
emit(evt, payload) { for (const h of this.handlers.get(evt) ?? []) h(payload); }
}
const bus = new EventBus();
bus.on('order.created', (o) => console.log('email:', o.id));
bus.on('order.created', (o) => console.log('audit:', o.id));
bus.emit('order.created', { id: 1 });
// ===== When patterns help =====
// - Naming a non-obvious relationship in code review ('this is a Strategy')
// - Refactoring towards a known shape
// - Teaching juniors a common vocabulary
// - Designing systems that need to evolve in known dimensions
// ===== When patterns hurt =====
// - Reaching for a pattern before you have the problem
// - Singletons everywhere -> hidden coupling + testing pain
// - 5-class factories where a function would do
// - Pattern soup that obscures the domain logic
// ===== Patterns to internalise =====
// - Strategy + Polymorphism replace switch-on-type
// - Composition over inheritance (Decorator, Adapter)
// - Dependency injection + small interfaces over service locators
// - Repository + Unit of Work for data access boundaries
// ===== Pitfalls =====
// - Singletons used as global state by another name
// - Visitor used where pattern matching is clearer
// - 'I will need this' factories for hypothetical futures
// - Layer cake that adds files without adding clarity
Why it matters
Patterns are vocabulary, not destinations. Learn the classics so you can recognise them in code reviews and design discussions. Reach for them when the shape fits the problem, not because the chapter is exciting. The best code is the simplest code that meets requirements; patterns are how you keep that simple as the requirements grow.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// Design patterns are battle-tested templates for common design problems.
// They give you a shared vocabulary ("this is an Observer") and a starting shape.
Try it Yourself »
Discussion
Loading…