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.
Purpose and Use Case
The Factory Method pattern suggests replacing direct object construction calls (using the new operator) with calls to a special factory method. It is ideal when you don't know beforehand the exact types and dependencies of the objects your code should work with.
Key Benefits (SOLID):
- Avoids tight coupling: Decouples the client code from concrete product classes.
- Single Responsibility Principle (SRP): Centralizes object creation logic into specific creator classes.
- Open/Closed Principle (OCP): You can introduce new product types into the application without breaking existing client code.
Pattern Structure
The conceptual architecture consists of four main elements:
- Product (Interface): Declares the interface common to all objects created by the creator and its subclasses.
- Concrete Products: Different implementations of the product interface.
- Creator (Abstract Class/Interface): Declares the factory method returning product objects.
- Concrete Creators: Override the base factory method to return instances of specific concrete products.
Cargando diagrama...
How It Works
- Interface Definition: Define a uniform interface for all products (e.g.,
Notification). - Concrete Implementation: Implement concrete classes (e.g.,
EmailNotification,SMSNotification,PushNotification). - Creator Hierarchy: Define an abstract creator with a
createNotification()factory method. - Subclass Delegation: Subclasses override the factory method to return specific instances based on business logic.
Real-World Implementation Examples
// 1. Product Interface
interface Notification {
send(message: string, recipient: string): void;
}
// 2. Concrete Products
class EmailNotification implements Notification {
send(message: string, recipient: string): void {
console.log(`[EMAIL] Sending "${message}" to ${recipient}`);
}
}
class SMSNotification implements Notification {
send(message: string, recipient: string): void {
console.log(`[SMS] Sending "${message}" to ${recipient}`);
}
}
class PushNotification implements Notification {
send(message: string, recipient: string): void {
console.log(`[PUSH] Sending "${message}" to device ${recipient}`);
}
}
// 3. Creator (Abstract Class)
abstract class NotificationFactory {
// Factory Method
public abstract createNotification(): Notification;
// Core business logic relying on factory method
public notify(message: string, recipient: string): void {
const notification = this.createNotification();
notification.send(message, recipient);
}
}
// 4. Concrete Creators
class EmailNotificationFactory extends NotificationFactory {
public createNotification(): Notification {
return new EmailNotification();
}
}
class SMSNotificationFactory extends NotificationFactory {
public createNotification(): Notification {
return new SMSNotification();
}
}
class PushNotificationFactory extends NotificationFactory {
public createNotification(): Notification {
return new PushNotification();
}
}
// Client Usage
function clientCode(factory: NotificationFactory) {
factory.notify("Your order has shipped!", "user@example.com");
}
clientCode(new EmailNotificationFactory());
clientCode(new SMSNotificationFactory());Practical Code Example
To see a real-world admin panel refactoring in React/TypeScript applying this pattern alongside SOLID and YAGNI, check out our practical example:
💡 View Practical Example: Factory Pattern Practical Example