Guide
Factory Comparison
Tell apart a factory function, static creation method, simple factory, Factory Method and Abstract Factory, and pick the smallest one that fits.
- Also known as
- Simple Factory, Static factory method, Creation method
Why the word is confusing
"Factory" is used for at least five different things. Only two of them are GoF patterns. Pick by asking who decides which concrete class to create, and whether several products must match.
The five meanings
1. Factory function or creation method
Any function or method that creates and returns an object. It replaces a direct new so construction can have a descriptive name or hide setup.
class Money {
private constructor(readonly cents: number, readonly currency: string) {}
static fromDecimal(amount: number, currency: string): Money {
return new Money(Math.round(amount * 100), currency);
}
static zero(currency: string): Money {
return new Money(0, currency);
}
}This is not a design pattern in the catalog; it is good practice. The refactoring that introduces it is Replace Constructor with Factory Method.
2. Static factory that picks a subtype
A creation method that returns one of several implementations based on an argument.
interface Notifier { send(to: string, body: string): Promise<void> }
function createNotifier(channel: "email" | "sms" | "push"): Notifier {
switch (channel) {
case "email": return new EmailNotifier();
case "sms": return new SmsNotifier();
case "push": return new PushNotifier();
}
}Often called a "simple factory". The switch lives in one place, so callers stay free of it. This covers most real needs. Adding a channel means editing this function, which is fine when it is the only place that knows about channels.
3. Simple factory class
The same idea as a class with one creation method, often so it can be injected or configured. Use it when the factory needs dependencies (API keys, a clock, a logger) that callers shouldn't see.
4. Factory Method (GoF)
A base class or framework defines a workflow and calls an overridable creation method. Subclasses, or injected functions, decide the concrete product. The point is that the code calling the factory is written before the product types are known.
abstract class ReportJob {
run(rows: Row[]): string {
const writer = this.createWriter(); // the factory method
rows.forEach((r) => writer.write(r));
return writer.finish();
}
protected abstract createWriter(): RowWriter;
}
class CsvReportJob extends ReportJob {
protected createWriter(): RowWriter { return new CsvWriter(); }
}See Factory Method. In TypeScript you can often pass () => RowWriter into the constructor instead of subclassing.
5. Abstract Factory (GoF)
An object that creates a family of related products that must be used together. Swapping the factory swaps the whole family consistently.
interface StorageKit {
blobStore(): BlobStore;
queue(): Queue;
lock(): DistributedLock;
}
class AwsKit implements StorageKit { /* S3, SQS, DynamoDB lock */ }
class LocalKit implements StorageKit { /* filesystem, in-memory queue, mutex */ }
function startWorker(kit: StorageKit) {
const blobs = kit.blobStore();
const jobs = kit.queue();
// blobs and jobs are guaranteed to come from the same environment
}See Abstract Factory.
Comparison table
| Variant | Who decides the concrete type | Products | Extend by |
|---|---|---|---|
| Creation method | The method itself (always one type) | One | Adding a named method |
| Simple factory | A switch or map inside the factory | One, of several types | Editing the factory |
| Factory Method | A subclass or injected function | One, used by a workflow | Adding a subclass or function |
| Abstract Factory | The chosen factory object | Several related ones | Adding a whole new factory |
Diagram source (Mermaid)
flowchart TD
A[Need to create an object] --> B{More than one concrete type?}
B -- No --> C[Creation method or plain constructor]
B -- Yes --> D{Several products that must match?}
D -- Yes --> E[Abstract Factory]
D -- No --> F{Does a workflow call creation before types are known?}
F -- Yes --> G[Factory Method]
F -- No --> H[Simple factory function]How to choose
- Start with a constructor. Move to a creation method when construction needs a name, validation or caching.
- Use a simple factory function when callers must not know concrete types, and selection is a lookup.
- Use Factory Method when a reusable workflow, framework hook or base class needs to create something that extensions customize.
- Use Abstract Factory only when mixing products from different families is a real bug risk.
- If the problem is many optional parameters, not which type to create, you want Builder.
- If new objects should copy a configured template, you want Prototype.
Common mistakes
- Creating an
XFactoryclass for every class with a plain constructor. That is Speculative Generality. - Building an Abstract Factory with one product method. That is a Factory Method or a simple factory with extra types.
- Subclassing only to override the factory method, in a language where passing a function works. Prefer composition.
See also
- Factory MethodLet a subclass or a supplied function decide which concrete object to create, so shared workflow code depends only on an interface.
- Abstract FactoryCreate families of related objects through one interface so client code always gets a matching set and never names the concrete classes.
- BuilderAssemble a complex object through named, step-by-step calls and validate it once in build(), instead of a constructor with many parameters.
- PrototypeCreate new objects by copying a configured existing instance, so callers get a ready-made variant without knowing its class or setup.
- Replace Constructor with Factory MethodWrap object creation in a named static or module function when a plain constructor cannot express intent, pick a subtype, or reuse instances.
Original writing and examples. Topic coverage follows Refactoring.Guru, which explains this topic with its own illustrations.