βοΈ Singleton Design Pattern in Java
The Singleton Pattern ensures a class has only one instance and provides a global access point to it.
Itβs one of the most used creational design patterns in real-world projects like:
- Logging
- Database connections
- Configuration managers
- Caches
π― Real-World Analogy
π§ Think of a government ID system. You only get one Aadhaar card, and itβs used across all systems. You donβt need multiple Aadhaar cards for different apps.
Same for singleton β one instance, used everywhere.
π§ When to Use Singleton?
- When only one instance should exist.
- When global access is required (but avoid overusing it like a global variable).
- When shared resources (e.g., file system, config manager, connection pool) are involved.
π₯ Basic Singleton Implementation
class Singleton {
private static Singleton instance;
private Singleton() {
// private constructor stops external instantiation
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // lazy initialization
}
return instance;
}
}
π‘ How to Use
Singleton obj = Singleton.getInstance();
β οΈ Problem: It's Not Thread-Safe!
If two threads call getInstance()
at the same time, it can create two objects. That's not what we want.
β Thread-Safe Singleton (Synchronized Method)
class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
π» Downside
Slower due to method-level locking (even when instance is already created).
β‘ Best Practice: Double-Checked Locking
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // First check (no lock)
synchronized (Singleton.class) {
if (instance == null) { // Second check (with lock)
instance = new Singleton();
}
}
}
return instance;
}
}
β Why This is Better?
- Fast after first use.
- Safe for multi-threaded access.
- Memory efficient (
volatile
avoids caching issues).
π§ͺ Singleton Using Enum (Simplest & Thread-Safe)
enum SingletonEnum {
INSTANCE;
public void show() {
System.out.println("Singleton using enum");
}
}
π‘ Usage
SingletonEnum.INSTANCE.show();
β Enum is thread-safe and prevents serialization/deserialization issues by default.
π Key Points to Remember
| Feature | Implementation |
| --------------- | ------------------------------- |
| Lazy Loading | getInstance()
method |
| Thread-Safe | Synchronized or Enum |
| Prevent new obj | Private constructor |
| Global Access | getInstance()
method |
| Avoid pitfalls | Use enum or double-checked lock |
π§° Singleton in a Real Project (Logger Utility Example)
public class Logger {
private static Logger logger;
private Logger() {}
public static Logger getInstance() {
if (logger == null) {
synchronized (Logger.class) {
if (logger == null) {
logger = new Logger();
}
}
}
return logger;
}
public void log(String message) {
System.out.println("LOG: " + message);
}
}
π§ͺ Usage in Main Class
public class App {
public static void main(String[] args) {
Logger logger = Logger.getInstance();
logger.log("App started");
Logger logger2 = Logger.getInstance();
logger2.log("Still same logger!");
System.out.println(logger == logger2); // true
}
}
β Output
LOG: App started
LOG: Still same logger!
true
π« Common Mistakes
- β Not handling multithreading in
getInstance()
. - β Creating a new object via reflection.
- β Forgetting to make the constructor
private
.
π‘οΈ Protection Against Reflection
class SafeSingleton {
private static SafeSingleton instance;
private SafeSingleton() {
if (instance != null) {
throw new RuntimeException("Use getInstance() method");
}
}
public static SafeSingleton getInstance() {
if (instance == null) {
instance = new SafeSingleton();
}
return instance;
}
}
π§ Interview Q&A
Q: Can Singleton break with Serialization?
A: Yes, unless you override readResolve()
method or use Enum.
Q: What design pattern category does Singleton belong to? A: Creational.
Q: Can you create a Singleton in Spring? A: Yes! Spring Beans are singleton-scoped by default.
π Summary
- β Use Singleton when exactly one object is needed.
- π§΅ Use thread-safe methods in concurrent applications.
- π Use Enum or double-check locking for best results.
- π« Avoid anti-patterns like excessive global access.