# Factory Comparison

> Tell apart a factory function, static creation method, simple factory, Factory Method and Abstract Factory, and pick the smallest one that fits.

- kind: guide
- category: design-patterns
- aliases: Simple Factory, Static factory method, Creation method
- canonical: https://aipatterns.dev/guides/factory-comparison
- inspired-by: https://refactoring.guru/design-patterns/factory-comparison

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

```ts
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](https://aipatterns.dev/refactoring/techniques/replace-constructor-with-factory-method.md).

### 2. Static factory that picks a subtype

A creation method that returns one of several implementations based on an argument.

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

```ts
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](https://aipatterns.dev/design-patterns/factory-method.md). 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.

```ts
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](https://aipatterns.dev/design-patterns/abstract-factory.md).

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

```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](https://aipatterns.dev/design-patterns/factory-method.md) when a reusable workflow, framework hook or base class needs to create something that extensions customize.
- Use [Abstract Factory](https://aipatterns.dev/design-patterns/abstract-factory.md) 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](https://aipatterns.dev/design-patterns/builder.md).
- If new objects should copy a configured template, you want [Prototype](https://aipatterns.dev/design-patterns/prototype.md).

## Common mistakes

- Creating an `XFactory` class for every class with a plain constructor. That is [Speculative Generality](https://aipatterns.dev/refactoring/smells/speculative-generality.md).
- 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.
