Singleton Design Pattern is a creational design pattern which ensures that a class has only one instance and provides a global point of access to that instance.
I know you might be thinking – “Why is there an entire design pattern just to make sure only one object is instantiated??”
To tell you the truth, generally it does not matter if you create multiple objects of a class in an applications. However in scenarios like logging, configuration handling or managing Database connections – you would need to instantiate just one instance in order to avoid redundancy, excessive memory use or inconsistent behavior.
But then you would think that – “Can’t we just create a global or static variable for the same?? After all we are just looking for a global point of access right??”
Well to be honest you can. BUT. . .
When you assign an object to a global variable, then that object might be created as soon as your application starts. What if this object is resource intensive and your application eventually ends up never using it. With singleton pattern we have the ability to create our object only when it is required.
Let’s create our first Singleton
So, generally this is how you would declare a normal class.
class MyFirstSingleton {
MyFirstSingleton() { . . . }
}When you declare a class in the above mentioned way, you can create multiple instances of the class, so basically the above is not a singleton class. But what if the constructor is private?

I know…I know, you would be thinking – “But having a private constructor means that this class cannot be instantiated. So how does this make any sense??”
Having a private constructor means no-one outside the MyFirstSingleton class can call it. So that would mean any method inside the MyFirstSingleton can call it’s constructor. And what if this some method is a static method?
class MyFirstSingleton {
private MyFirstSingleton() { . . . }
public static MyFirstSingleton getInstance() {
return new MyFirstSingleton();
}
}The getInstance is a CLASS variable, so you can actually call it like: MyFirstSingleton.getInstance()
And this will create an object of the MyFirstSingleton class.
But we are still creating a new instance of MyFirstSingleton class on calling getInstance(), which defeats the purpose of singleton.
In that case how do we create an actual singleton class?
There are 2 ways to creating a singleton class:

Eager Loading
You can create an eagerly loaded singleton like:
class EagerSingleton {
// Eagerly created singleton instance
private static EagerSingleton singleton = new EagerSingleton();
// Private constructor
private EagerSingleton() { . . . }
public static EagerSingleton getInstance() {
// Always returns the same instance
return singleton;
}
}In eager loading, the singleton instance is created when the class is loaded, even if it is never used.
The eager loading way of implementing singleton is inherently thread-safe, but wastes memory if the instance is never used. Hence it is not suitable for heavy objects.
Lazy Loading
Unlike Eager loading, in lazy loading the idea💡 in Lazy loading is to create the object only if and when it’s required. Let’s create a basic lazy loaded singleton class.
class LazySingleton {
// Lazily initialized singleton instance
private static LazySingleton instance;
// Private constructor
private LazySingleton() {. . . }
// Returns singleton instance of the class
public static LazySingleton getInstance() {
if(instance == null) {
instance = new LazySingleton();
}
return instance;
}
}Lets understand the getInstance() method in a bit more detail.

In a single-threaded environment, this code works fine. BUT BUT BUT . . .
In a multi-threaded environment, it is possible that 2 threads call getInstance() at the same time when instance is null, both might create separate instances, violating the Singleton pattern.
So, this way of creating singleton is not inherently thread-safe 😖.
But worry not, there are 3 ways to make your lazy loaded singleton classes thread-safe 😎.

Synchronized Keyword
Using the synchronized keyword is the easiest way to ensure thread-safety. However, this approach can lead to performance issues due to synchronization overhead.
class LazySingleton {
// Lazily initialized singleton instance
private static LazySingleton instance;
// Private constructor
private LazySingleton() {. . . }
// Returns singleton instance of the class
public static synchronized LazySingleton getInstance() {
if(instance == null) {
instance = new LazySingleton();
}
return instance;
}
}By adding synchronized keyword to getInstance(), we force every thread to wait for its turn before it can enter the method. Hence, no two threads can enter the method at the same time.
BUT…the only time synchronization is relevant is the first time. Once we have set the instance to variable to a singleton instance, we have no further need to synchronize this method. This may slow down system in high concurrency scenarios.
Double-checked locking
Here, we check if the instance is null before acquiring the lock. If it is, then we synchronize the block and check again. This reduces the overhead of synchronization after the instance is created.
class LazySingleton {
// Lazily initialized singleton instance
private static volatile LazySingleton instance;
// Private constructor
private LazySingleton() {. . . }
// Returns singleton instance of the class
public static LazySingleton getInstance() {
// Outer if avoids synchronization once the instance is created
if(instance == null) {
synchronized(LazySingleton.class) {
// Inner if ensures that only one thread creates the instance
if(instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}The volatile keyword ensures changes made by one thread are visible to other threads. Without volatile, one thread might create singleton instance but other threads might not be able to see the updated value due to caching. Volatile makes sure that the instance is always read from main memory, so that the threads see the most recent version of data.
Bill Pugh Singleton
This approach efficiently implements the Singleton pattern by using a static inner class to hold the instance. The inner class—and therefore the singleton—is loaded only when getInstance() is called for the first time.
class LazySingleton {
// Private constructor
private LazySingleton() {. . . }
// Static inner class holding lazy singleton instance
private static class Holder {
private static final LazySingleton INSTANCE = new LazySingleton();
}
// Returns singleton instance of the class
public static LazySingleton getInstance() {
return Holder.INSTANCE;
}
}As the static inner class is not loaded until referenced, it ensures thread-safety and high performance without the overhead of synchronization.
Singleton using Enums – The BEST approach
Using Enums is one of the best ways to implement singleton as it is clean concise and thread-safe.
public enum Singleton {
INSTANCE;
// Some getter-setter to give an example of some functionality
int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
// Driver code
public class Demo {
public static void main(String[] args) {
Singleton singleton = Singleton.INSTANCE;
singleton.setValue(2);
System.out.println(singleton.getValue()); // Outputs 2
}
}Some tricky points about Singleton
Does Singleton follow Single Responsibility Principle??
The answer is — you guessed it — a definite NO.
Singleton violates SRP as it handles both instance-control and core class functionality.
Is it possible to create subclasses of Singleton?
Well, the constructor of a singleton is private, so in order to extend it you would need to change it to public or protected – in which case it would no longer be a singleton. So, NO you cannot create sub-classes for a singleton.
And with that, we’ve wrapped up the Singleton Design Pattern — you’re now fully equipped with everything you need to know on Singleton 🎉.