Introduction to Singleton Pattern
Singleton ensures a class has only one instance while providing a global access point.
The Problem
Some resources should only have one instance:
- Configuration managers
- Connection pools
- Logger instances
- Rate limiters
typescript1// Without Singleton - multiple instances cause issues2const config1 = new Configuration();3const config2 = new Configuration();4config1.set('apiKey', 'key1');5config2.set('apiKey', 'key2');6// Which one is correct? Inconsistent state!
The Solution: Singleton
typescript1class Configuration {2 private static instance: Configuration;3 private settings: Map<string, string> = new Map();45 private constructor() {} // Private constructor67 static getInstance(): Configuration {8 if (!Configuration.instance) {9 Configuration.instance = new Configuration();10 }11 return Configuration.instance;12 }1314 get(key: string): string | undefined {15 return this.settings.get(key);16 }1718 set(key: string, value: string): void {19 this.settings.set(key, value);20 }21}2223// Usage24const config1 = Configuration.getInstance();25const config2 = Configuration.getInstance();26config1 === config2; // true - same instance
When to Use
- Shared resources - Database connections, caches
- Configuration - Global settings
- Logging - Single log destination
- Rate limiting - Track API calls globally
Criticisms and Alternatives
Problems with Singleton:
- Global state makes testing harder
- Hidden dependencies
- Violates Single Responsibility Principle
Alternatives:
- Dependency Injection (preferred)
- Module-level instance
- IoC containers
Summary
Use Singleton sparingly. Often Dependency Injection is a better solution for managing shared resources.