Creational Patterns • Singleton PatternMedium⏱️ ~2 min
Singleton Pattern: Structure and Implementation Strategies
Core Structure:
The Singleton Pattern involves a single class that manages its own unique instance. The structure consists of three key elements: private constructor, private static instance variable, and public static accessor method.
Singleton
- instance: Singleton (static)
- data: ConfigData
- data: ConfigData
- Singleton() [private constructor]
+ getInstance(): Singleton (static)
+ getData(): ConfigData
+ setData(data: ConfigData): void
+ getInstance(): Singleton (static)
+ getData(): ConfigData
+ setData(data: ConfigData): void
Three Implementation Strategies:
First: Eager Initialization
The instance is created at class loading time, before any thread accesses it.
Second: Lazy Initialization
The instance is created only when first requested via
Third: Double-Checked Locking (Lazy with Thread Safety)
Combines lazy initialization with minimal locking overhead.
The instance is created at class loading time, before any thread accesses it.
class Singleton:
instance = new Singleton() // created immediately
private Singleton():
// initialization code
public static getInstance():
return instance
Trade-off: Simple and thread-safe by default, but creates instance even if never used (wastes resources). Appropriate when the instance is lightweight and always needed.instance = new Singleton() // created immediately
private Singleton():
// initialization code
public static getInstance():
return instance
Second: Lazy Initialization
The instance is created only when first requested via
getInstance().class Singleton:
instance = null // not created yet
private Singleton():
// initialization code
public static getInstance():
if instance is null:
instance = new Singleton()
return instance
Trade-off: Saves memory if never used, but requires thread-safety mechanisms (locking) in multi-threaded environments, which adds complexity.instance = null // not created yet
private Singleton():
// initialization code
public static getInstance():
if instance is null:
instance = new Singleton()
return instance
Third: Double-Checked Locking (Lazy with Thread Safety)
Combines lazy initialization with minimal locking overhead.
class Singleton:
instance = null // volatile/synchronized
public static getInstance():
if instance is null: // first check (no lock)
lock():
if instance is null: // second check (with lock)
instance = new Singleton()
return instance
Trade-off: Optimizes performance by avoiding lock contention after initialization, but implementation is subtle and error-prone if not done correctly.instance = null // volatile/synchronized
public static getInstance():
if instance is null: // first check (no lock)
lock():
if instance is null: // second check (with lock)
instance = new Singleton()
return instance
Interview Tip: Be prepared to discuss thread safety. Interviewers often ask how you handle concurrent access to
getInstance() in multi-threaded environments.Critical Design Decision:
The private constructor prevents external instantiation. Subclassing is also prevented because subclasses cannot call the private constructor. If subclassing is needed, consider using the Factory Pattern instead.
💡 Key Takeaways
✓Private constructor prevents external instantiation
✓Static instance variable holds the single instance
✓Static getInstance() method provides global access point
✓Eager initialization creates instance at class load time
✓Lazy initialization defers creation until first access
✓Double-checked locking optimizes thread-safe lazy initialization
📌 Examples
1Eager: DatabaseConnectionPool initialized at startup
2Lazy: HeavyResourceManager created only when needed
3Double-checked: ThreadSafeLogger with minimal locking overhead