🔍 What is the Singleton Design Pattern?
The Singleton Pattern is a creational design pattern that ensures a class has only one instance and provides a global point of access to it.
✅ When Should You Use It?
- To manage shared resources like database connections, thread pools, caches, logging, etc.
- When you want to restrict object creation to only one instance throughout the application lifecycle.
🧠 Real-World Analogy
Think of the President of a country. There is only one President at any given time. If anyone tries to create another one, it should return the same instance 👑.
🧱 Structure
We’ll cover 4 variations of Singleton in Java:
- Basic Singleton (Lazy Initialization)
- Thread-Safe Singleton (Synchronized)
- Bill Pugh Singleton (Best Practice)
- Enum Singleton (Most Robust)
✅ 1. Lazy Initialization (Not Thread-Safe)
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {} // private constructor
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
❌ Not thread-safe. Two threads may create two instances.
✅ 2. Thread-Safe Singleton (Synchronized)
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton() {}
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}
✅ Thread-safe, but slower due to synchronization.
✅ 3. Bill Pugh Singleton (Recommended)
public class BillPughSingleton {
private BillPughSingleton() {}
private static class Holder {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance() {
return Holder.INSTANCE;
}
}
✅ Thread-safe, fast, and lazy-loaded. Best practice in most cases.
✅ 4. Enum Singleton (Robust & Safe)
public enum EnumSingleton {
INSTANCE;
public void doSomething() {
System.out.println("Doing something from Enum Singleton");
}
}
✅ Simplest and safest, handles serialization, reflection, and thread safety.
💻 Client Code
public class SingletonDemo {
public static void main(String[] args) {
LazySingleton s1 = LazySingleton.getInstance();
LazySingleton s2 = LazySingleton.getInstance();
System.out.println("Same LazySingleton? " + (s1 == s2)); // true
BillPughSingleton b1 = BillPughSingleton.getInstance();
BillPughSingleton b2 = BillPughSingleton.getInstance();
System.out.println("Same BillPughSingleton? " + (b1 == b2)); // true
EnumSingleton.INSTANCE.doSomething();
}
}
🧪 Output:
Same LazySingleton? true
Same BillPughSingleton? true
Doing something from Enum Singleton
⚙️ UML Diagram (Text Format)
+--------------------+
| SingletonClass |
+--------------------+
| -instance: static |
| -constructor() |
+--------------------+
| +getInstance(): SingletonClass |
+--------------------+
🧑🏫 Key Takeaways
- Singleton ensures only one instance exists.
- Use Bill Pugh or Enum versions in production.
- Useful for centralized services like logging, config, DB access.
🚀 Up Next for Day 4: Want to explore Decorator, Strategy, or Adapter?
Let me know your pick, and I’ll keep the clean breakdown + rich Java code style coming!