Commissioned for this museum · after Gamma, Helm, Johnson & Vlissides, 1994
Singleton
TypeScript·1994·30 lines·770 bytes
/**
* Singleton — one instance, globally reachable, created on first use.
*/
class Registry {
private static instance: Registry | null = null;
private readonly entries = new Map<string, unknown>();
// The constructor is private, so `new Registry()` is a compile error.
// This is the whole trick: the class takes away your ability to make one.
private constructor() {}
static getInstance(): Registry {
if (Registry.instance === null) {
Registry.instance = new Registry();
}
return Registry.instance;
}
set(key: string, value: unknown): void {
this.entries.set(key, value);
}
get(key: string): unknown {
return this.entries.get(key);
}
}
// Everywhere in the program, this is the same object.
Registry.getInstance().set("theme", "dark");Curator’s note
This is the most famous of the twenty-three patterns and the only one the authors later regretted. It is hung here the way a museum hangs an instrument of torture: not in admiration, but because you cannot understand the period without it.
Look at what the private constructor actually does. It does not make the object a singleton — the static field does that. What it does is remove your ability to make a second one, permanently, for every caller, including the test you will write next year. The pattern's mechanism *is* the removal of a choice from everyone downstream of it.
Two things follow, and both are visible in these thirty lines. There is no way to reset Registry.instance, so a test that mutates the registry leaks into the test after it. And getInstance() names no dependency, so a function that calls it looks self-contained in its own signature while being coupled to global state. The type system, which is otherwise so talkative in TypeScript, has nothing to say about either.
The form is genuinely beautiful — six lines of lazy initialisation that have been copied into more codebases than almost any other fragment in this building. It is worth admiring the economy while remembering that a modern version of this file is usually one exported const, or a parameter.