The Singleton Design Pattern is one of the creational design patterns. Its primary intent is to ensure that a class has only one instance and provides a global point of access to that instance. Singleton ensures that only one object is created, even if multiple clients try to instantiate it.
Singleton is useful in situations where only one instance of a class should exist throughout the application's lifecycle. Common scenarios include:
In eager initialization, the Singleton instance is created at the time of class loading. This is the simplest form of Singleton, and the instance is created irrespective of whether it is needed or not.
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
// Private constructor to prevent instantiation
}
public static EagerSingleton getInstance() {
return instance;
}
}
Lazy initialization defers the creation of the Singleton instance until it is requested. This can help in situations where the instance is resource-heavy or costly to create, and you want to delay its creation until necessary.
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
// Private constructor
}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
The Singleton pattern can be broken using reflection because reflection allows the private constructor to be accessed, thus bypassing the Singleton mechanism.
import java.lang.reflect.Constructor;
public class ReflectionSingletonBreaker {
public static void main(String[] args) throws Exception {
EagerSingleton instanceOne = EagerSingleton.getInstance();
Constructor constructor = EagerSingleton.class.getDeclaredConstructor();
constructor.setAccessible(true); // Bypassing private constructor
EagerSingleton instanceTwo = constructor.newInstance();
System.out.println(instanceOne == instanceTwo); // Prints false, breaking Singleton
}
}
enum
for Singleton implementation.
In multi-threaded environments, lazy Singleton can lead to multiple instances being created. Thread-safe Singleton ensures that even if multiple threads access the getInstance()
method simultaneously, only one instance is created.
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton() {
// Private constructor
}
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}