Factory Method
Overview
Define an interface for creating objects, but let subclasses decide which class to instantiate.
When to use
- The exact concrete type is decided at runtime.
- You want to decouple creation logic from usage.
Java example
interface Exporter {
String export(String data);
}
class JsonExporter implements Exporter {
public String export(String data) {
return "{\"data\":\"" + data + "\"}";
}
}
class CsvExporter implements Exporter {
public String export(String data) {
return "data\n" + data + "\n";
}
}
abstract class ExporterFactory {
public abstract Exporter create();
}
class JsonExporterFactory extends ExporterFactory {
public Exporter create() {
return new JsonExporter();
}
}
TypeScript example
interface Exporter {
export(data: string): string;
}
class JsonExporter implements Exporter {
export(data: string): string {
return JSON.stringify({ data });
}
}
class CsvExporter implements Exporter {
export(data: string): string {
return `data\n${data}\n`;
}
}
abstract class ExporterFactory {
abstract create(): Exporter;
}
class JsonExporterFactory extends ExporterFactory {
create(): Exporter {
return new JsonExporter();
}
}
Pros and cons
Pros:
- Centralizes creation logic.
- Enables substitution of product types.
Cons:
- Adds extra classes.
- Can be overkill for simple creation.
Common pitfalls
- Returning different product types from the same factory.
- Pushing too much logic into the factory.