Factory Pattern
The Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
The Problem
Imagine you’re creating a logistics management application. The first version of your app can only handle transportation by Trucks. Most of your code lives inside the Truck class.
After a while, your app becomes popular, and you need to incorporate Ships into the logistics. Adding Ship to the codebase requires changing the entire core logic, which is coupled to Truck.
The Solution: Factory Method
The Factory Method suggests that you replace direct object construction calls (new Truck()) with calls to a special factory method.
Class Diagram
classDiagram
class Logistic {
+planDelivery()
+createTransport() Transport*
}
class RoadLogistic {
+createTransport() Transport
}
class SeaLogistic {
+createTransport() Transport
}
class Transport {
<<interface>>
+deliver()
}
class Truck {
+deliver()
}
class Ship {
+deliver()
}
Logistic <|-- RoadLogistic
Logistic <|-- SeaLogistic
Transport <.. Logistic
Transport <|.. Truck
Transport <|.. Ship
Implementation in TypeScript
interface Transport {
deliver(): string;
}
class Truck implements Transport {
deliver() { return "Delivering by land in a crate."; }
}
class Ship implements Transport {
deliver() { return "Delivering by sea in a container."; }
}
// The Creator class
abstract class Logistics {
public abstract createTransport(): Transport;
public planDelivery(): string {
const transport = this.createTransport();
return `Logistics: ${transport.deliver()}`;
}
}
class RoadLogistics extends Logistics {
public createTransport(): Transport {
return new Truck();
}
}
class SeaLogistics extends Logistics {
public createTransport(): Transport {
return new Ship();
}
}
// Client Code
function startLogistics(creator: Logistics) {
console.log(creator.planDelivery());
}
startLogistics(new RoadLogistics());
startLogistics(new SeaLogistics());
Why it matters
- Decoupling: The high-level
Logisticsclass doesn't need to know the specific types ofTransportit creates. - Single Responsibility: You can move the product creation code into one place in the program.
- Open/Closed Principle: You can introduce new types of products into the program without breaking existing client code.