Factory Pattern

What Is It?
Why Use It?
- You don’t want your code to depend directly on concrete classes (e.g., Truck, Ship).
- You want to be able to add new types of objects without touching existing code.
- You want to encapsulate object creation logic.
Real-World Analogy
- RoadLogistics → creates a Truck
- SeaLogistics → creates a Ship
TypeScript Example
Ts
// Product interface
interface Transport {
deliver(): void;
}
// Concrete Products
class Truck implements Transport {
deliver(): void {
console.log("Delivering by land in a box.");
}
}
class Ship implements Transport {
deliver(): void {
console.log("Delivering by sea in a container.");
}
}
// Creator (abstract class)
abstract class Logistics {
// Factory method to be implemented by subclasses
abstract createTransport(): Transport;
// Business logic that depends on the Transport interface
planDelivery(): void {
const transport = this.createTransport();
transport.deliver();
}
}
// Concrete Creators
class RoadLogistics extends Logistics {
createTransport(): Transport {
return new Truck();
}
}
class SeaLogistics extends Logistics {
createTransport(): Transport {
return new Ship();
}
}
// Client code
function app(logistics: Logistics) {
logistics.planDelivery();
}
const roadLogistics = new RoadLogistics();
const seaLogistics = new SeaLogistics();
app(roadLogistics); // Delivering by land in a box.
app(seaLogistics); // Delivering by sea in a container.
When to Use Factory Method
- You need to decouple object creation from usage.
- You want to add new object types without changing core logic.
- You’re building a framework or library others will extend.
- You want to optionally reuse or pool objects.
Pros & Cons
- Removes direct dependency on concrete classes
- Easier to test and extend
- Follows Open/Closed Principle
- Centralizes creation logic
- Adds more classes and boilerplate
- Can feel overkill for simple scenarios