Skip to main content

Factory Pattern

Creates objects without specifying their concrete classes

Pattern Overview

🏗️ The Factory Pattern - Object Creation Made Simple

Creates objects without specifying the exact class to create. Perfect for when you need flexibility in object creation!

  • Core Problem Solved:
  • Decouple object creation from usage
  • Support multiple product types
  • Enable runtime object type decisions
  • Centralize creation logic
🔍 Three Implementation Approaches:
  • Simple Factory: Static method returns objects based on input
  • Factory Method: Virtual method subclasses can override
  • Abstract Factory: Create families of related objects
  • Real-World Applications:
  • UI component libraries (buttons, inputs, modals)
  • Database connection managers
  • Payment processor selection
  • Plugin systems and middleware
  • API client generators
  • Configuration-based object creation
  • Modern Usage Examples:
  • React component factories
  • Database ORM adapters
  • Microservice client factories
  • Cloud provider abstractions

Examples:
Logging system - create appropriate logger based on configuration
Input:
LoggerFactory.createLogger('console')
Output:
ConsoleLogger instance
Component library - generate UI elements based on type and props
Input:
uiFactory.createComponent('button', 'Click me')
Output:
Button component instance
E-commerce - select payment provider based on user preference
Input:
PaymentProcessorFactory.createProcessor('stripe')
Output:
StripeProcessor instance
Dynamic UI - generate and display components programmatically
Input:
factory.createAndRender('modal', 'Alert', 'Save changes?')
Output:
Rendered modal HTML string

Concepts

Object CreationClass AbstractionRuntime DecisionsCentralized LogicType Flexibility

Complexity Analysis

Time:O(1) - constant time creation
Space:O(1) - per created object

Implementation

LoggerFactory

Time: O(1) | Space: O(1)
// Simple Factory Implementation
interface Logger {
  log(message: string): void;
  getType(): string;
}

class ConsoleLogger implements Logger {
  log(message: string): void {
    console.log(`[CONSOLE] ${new Date().toISOString()}: ${message}`);
  }

  getType(): string {
    return 'console';
  }
}

class FileLogger implements Logger {
  constructor(private filename: string) {}

  log(message: string): void {
    const logEntry = `[FILE:${this.filename}] ${new Date().toISOString()}: ${message}`;
    console.log(`Writing to file: ${logEntry}`);
  }

  getType(): string {
    return 'file';
  }
}

class LoggerFactory {
  public static createLogger(type: string, config?: string): Logger {
    switch (type.toLowerCase()) {
      case 'console':
        return new ConsoleLogger();
      case 'file':
        return new FileLogger(config || 'app.log');
      default:
        throw new Error(`Unknown logger type: ${type}`);
    }
  }
}