Skip to main content

Singleton Pattern

Ensures a class has only one instance with global access point

Pattern Overview

🏗️ The Singleton Pattern - Single Instance Control

Ensures a class has only one instance while providing global access to that instance. Essential for managing shared resources!

  • Core Problem Solved:
  • Need exactly one instance of a class
  • Global access point required
  • Prevent multiple instantiation
  • Control resource allocation
🔍 Three Implementation Approaches:
  • Class-based: Traditional OOP with private constructor
  • Closure-based: Functional approach using JavaScript closures
  • Module-based: ES6 modules are naturally singleton
  • Real-World Applications:
  • Database connection pools
  • Logging systems and audit trails
  • Configuration managers
  • Cache systems and registries
  • Redux stores in React apps
  • Modern Considerations:
  • Thread safety in Node.js
  • Module loading behavior
  • Memory management
  • Testing challenges and mocking

Examples:
Database connection pool - ensure only one connection manager exists
Input:
DatabaseConnection.getInstance()
Output:
DatabaseConnection instance
Application logging - single logger prevents file conflicts
Input:
createLoggerSingleton()
Output:
Logger instance
App configuration - one source of truth for all settings
Input:
appConfig.get('apiUrl')
Output:
'https://api.example.com'
Verify singleton behavior - all calls return same instance
Input:
Multiple getInstance() calls
Output:
Same instance reference

Concepts

Single InstanceGlobal AccessLazy InitializationResource ControlPrivate Constructor

Complexity Analysis

Time:O(1) - constant time access
Space:O(1) - single instance storage

Implementation

DatabaseConnection

Time: O(1) | Space: O(1)
// Class-based Singleton (Traditional)
export class DatabaseConnection {
  private static instance: DatabaseConnection | null = null;
  private connected: boolean = false;
  private connectionId: string;

  private constructor() {
    this.connectionId = Math.random().toString(36).substr(2, 9);
    this.connect();
  }

  public static getInstance(): DatabaseConnection {
    if (!DatabaseConnection.instance) {
      DatabaseConnection.instance = new DatabaseConnection();
    }
    return DatabaseConnection.instance;
  }

  private connect(): void {
    this.connected = true;
    console.log(`Database connected with ID: ${this.connectionId}`);
  }

  public query(sql: string): string {
    if (!this.connected) {
      throw new Error('Database not connected');
    }
    return `Executing: ${sql} on connection ${this.connectionId}`;
  }

  public getConnectionId(): string {
    return this.connectionId;
  }

  public isConnected(): boolean {
    return this.connected;
  }
}