Chapter 02
Creational patterns
The five patterns that decide how objects get created, so calling code does not depend on concrete classes or messy constructors.
Factory Method
Also called virtual constructor, factory
- What
- Intent: let a method decide which class to instantiate, so callers ask for "a transport" without naming the class.
- Why
- When: the exact type depends on configuration, input or subclass, and you want one place to change it.
interface Payment { pay(amount: number): void; }
function createPayment(kind: 'card' | 'wallet'): Payment {
switch (kind) {
case 'card': return new CardPayment();
case 'wallet': return new WalletPayment();
}
}Watch out
A factory that grows a huge switch touched by every feature; register creators in a map instead.
Abstract Factory
Also called kit, family of objects
- What
- Intent: an interface for creating whole families of related objects, with one concrete factory per family.
- Why
- When: products must match each other, such as light and dark UI widgets or one cloud provider's storage and queue clients.
interface UiFactory {
button(): Button;
dialog(): Dialog;
}
class DarkUi implements UiFactory { /* dark parts */ }
class LightUi implements UiFactory { /* light parts */ }
const ui: UiFactory =
prefersDark ? new DarkUi() : new LightUi();Builder
Also called fluent builder, step builder
- What
- Intent: construct a complex object step by step, separating how it is assembled from what it ends up as.
- Why
- When: a constructor would take many optional parameters, or construction needs validation before the object exists.
const req = new RequestBuilder('https://api.site.pk/users')
.method('POST')
.header('Authorization', token)
.json({ name: 'Sara' })
.timeout(5000)
.build();Watch out
Adding a builder for objects with two fields; named arguments or an options object are simpler.
Prototype
Also called clone
- What
- Intent: create new objects by copying an existing, configured instance instead of building from scratch.
- Why
- When: setup is expensive or the exact class is unknown to the caller, such as duplicating shapes in an editor.
interface Shape { clone(): Shape; }
class Circle implements Shape {
constructor(public r: number, public color: string) {}
clone() { return new Circle(this.r, this.color); }
}Watch out
Shallow copies that share nested objects, so editing the copy changes the original.
Singleton
Also called single instance
- What
- Intent: ensure a class has exactly one instance and give global access to it.
- Why
- When: one shared resource, such as a configuration object or a connection pool, must not be duplicated.
// In JS and TS a module is already a single instance
export const config = loadConfig();
// Classic form
class Registry {
private static instance?: Registry;
static get() { return (this.instance ??= new Registry()); }
}Watch out
Using singletons as hidden global state, which makes tests order-dependent; pass the instance in instead.