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
- 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 instanceApplication logging - single logger prevents file conflicts
Input:
createLoggerSingleton()Output:
Logger instanceApp 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() callsOutput:
Same instance referenceConcepts
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;
}
}