Creational Design Pattern – Initial Concept
This springcavaj – Creational Design Pattern page briefly describes the Initial Concept of Creational Design Patterns, advantages, disadvantages, benefits, various types, common problems, and a few interview questions discussed.
This guide will provide a deep understanding of Creational Design Patterns for designing and architecting an application.
What is a Singleton Design Pattern?
The Singleton Pattern is a Creational Design Pattern that ensures only one class instance exists and provides a global access point to that instance. This is useful when exactly one object is needed to coordinate actions across a system, such as managing configurations, database connections, or logging mechanisms.
What are the features of the Singleton Design Pattern?
- Single Instance – Ensures only one instance of a class exists throughout the application’s lifecycle.
- Global Access Point – The instance is globally accessible across the application.
- Eager or Lazy Initialization – The instance can be created at application startup (eager) or when required (lazy).
- Thread Safety – A proper implementation should handle multi-threaded access safely.
- Prevents Instantiation via Constructor – The constructor is private to prevent direct instantiation.
What are the advantages of Singleton Design Patterns?
- Saves Memory – Memory usage is optimized since only one instance is created.
- Prevents Duplicate Objects – Avoids unnecessary object creation, improving performance.
- Centralized Access to Resources – Ensures a single, coordinated access point for shared resources like databases or loggers.
- Encapsulation of State – Helps manage shared data consistency across an application.
What are the disadvantages of Singleton Design Patterns?
- Global State Can Be Risky – It can lead to unintended side effects due to uncontrolled access.
- Tightly Coupled Code – Singleton can make unit testing difficult since the instance is shared.
- Concurrency Issues – Improper implementation can cause race conditions in multi-threaded environments.
- Difficult to Mock – Since it is globally accessible, mocking a singleton in tests is challenging.
What are the use cases of Singleton Design Patterns?
- Database Connection Pooling – Managing a single connection instance.
- Logging System – Ensuring a single logging instance.
- Thread Pool Manager – Avoids unnecessary thread creation.
- Caching – Shared cache instance to optimize memory.
- Configuration Settings – One instance to hold app settings.
Singleton Design Pattern in Distributed Systems
Registry-Based Singleton Design Pattern
Database Backed Singleton Design Pattern
Brief description of implementation
I have developed a small program to help you understand the Singleton Design Pattern’s Working Principle. The code is uploaded to GitHub as springcavaj-designpattern repository. Please clone the application and import in any of the IDs like either STS or Eclipse.
After successfully importing the above code base, a class named SingletonMasterclassApplication.java will be found in the package as com.springcavaj.designpattern.singleton. Please see the screenshot attached below.

Here you can see the class under the com.springcavaj.designpattern.singleton package is SingletonMasterclassApplication.java. Right-click on the class, select the Run As option, and then Java Application. It will run and generate the output as provided below.
INFO com.springcavaj.designpattern.singleton.SingletonMasterclassApplication - Eager Initialization Singleton : 2047329716
INFO com.springcavaj.designpattern.singleton.SingletonMasterclassApplication - Lazy Initialization Singleton (Not Thread-safe): 96639997
INFO com.springcavaj.designpattern.singleton.SingletonMasterclassApplication - Thread-safe Singleton (Using synchronized method): 128893786
INFO com.springcavaj.designpattern.singleton.SingletonMasterclassApplication - Efficient Thread-safe Singleton (Double Checking): 1732398722
INFO com.springcavaj.designpattern.singleton.SingletonMasterclassApplication - Bill Pugh Singleton (Best Practice): 1108411398
In the above output, one can notice I have printed the hash value of all the types of mechanisms applicable to the Singleton Design Pattern. The values are different, representing different mechanisms of the Singleton Design Pattern.
Detailed Explanation
In this small program, I have defined different types of implementations of the Singleton Design Pattern. I will provide the advantages and disadvantages of each of the implementations of the Singleton Design Pattern.
Singleton Principles
- The Instance variable should be volatile, which means shared by the threads
- The Constructor should be private, with no instantiation, and inside the constructor to avoid creating objects using reflection, safeguard the code by checking if the instance of that class is not null then throw an exception.
- A method should be present which is public and static in nature and will return the instance of the class.
- It should override the readResolve() method to avoid creating objects using the Serialization process.
- It also should override the clone() method to avoid creating objects using the Clone functionality.
Eager Initialization Singleton
Eager Initialization Singleton is one type of implementation of the Singleton Design Pattern, where the instance is created at class loading time.
- Advantages – Simple, thread-safe
- Disadvantages – Instance is created even if never used, wasting memory
I have defined a class named EagerInitializationSingleton.java where I have written the code for the Eager Initialization Singleton.
public class EagerInitializationSingleton {
private static final EagerInitializationSingleton instance = new EagerInitializationSingleton();
private EagerInitializationSingleton() {
if(null != instance) {
throw new RuntimeException("Use getInstance() method to create instance not using Constructor uisng Reflection.");
}
}
public static EagerInitializationSingleton getInstance() {
return instance;
}
protected Object readResolve() {
return getInstance();
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Cannot clone singleton");
}
}
Lazy Initialization Singleton (Not Thread-safe)
Lazy Initialization Singleton is another type of implementation of the Singleton Design Pattern, where the instance is created when first accessed.
- Advantages – Simple
- Disadvantages – Not thread-safe. Multiple threads can create multiple instances. Hence, violating Singleton Design Principles.
I have defined a class named LazyInitializationSingleton.java where I have written the code for the Lazy Initialization Singleton (not thread-safe).
public class LazyInitializationSingleton {
private static LazyInitializationSingleton instance;
private LazyInitializationSingleton() {
if(null != instance) {
throw new RuntimeException("Use getInstance() method to create instance not using Constructor uisng Reflection.");
}
}
public static LazyInitializationSingleton getInstance() {
if(null == instance) {
instance = new LazyInitializationSingleton();
}
return instance;
}
protected Object readResolve() {
return getInstance();
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Cannot clone singleton");
}
}
Thread-Safe Singleton (using Synchronized)
Thread-safe Singleton is another type of implementation of the Singleton Design Pattern, where the instance is created when first accessed, but it is thread-safe due to the use of a synchronized keyword.
- Advantages – Thread-safe
- Disadvantages – Performance overhead due to method synchronization.
I have defined a class named ThreadSafeSingletonSynchronized.java where I have written the code for the Thread-safe Singleton using the synchronized keyword.
public class ThreadSafeSingletonSynchronized {
private static ThreadSafeSingletonSynchronized instance;
private ThreadSafeSingletonSynchronized() {
if(null != instance) {
throw new RuntimeException("Use getInstance() method to create instance not using Constructor uisng Reflection.");
}
}
public static synchronized ThreadSafeSingletonSynchronized getInstance() {
if(null == instance) {
instance = new ThreadSafeSingletonSynchronized();
}
return instance;
}
protected Object readResolve() {
return getInstance();
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Cannot clone singleton");
}
}
Double-Checked Locking (Efficient Thread-safe Singleton)
Double-checked locking is one of the efficient ways of implementing the Singleton Design pattern which is thread-safe and no performance overhead scenario arises.
- Advantages – Efficient, thread-safe without excessive synchronization.
- Disadvantages – Complexity increases due to volatile keyword.
I have defined a class named LazyInitializationSingletonDoubleChecking.java where I have written the code for the Double-checked locking thread-safe Singleton using the synchronized keyword efficiently.
public class LazyInitializationSingletonDoubleChecking {
private static volatile LazyInitializationSingletonDoubleChecking instance;
private LazyInitializationSingletonDoubleChecking() {
if(null != instance) {
throw new RuntimeException("Use getInstance() method to create instance not using Constructor uisng Reflection.");
}
}
public static LazyInitializationSingletonDoubleChecking getInstance() {
if(null == instance) {
synchronized (LazyInitializationSingletonDoubleChecking.class) {
if(null == instance) {
instance = new LazyInitializationSingletonDoubleChecking();
}
}
}
return instance;
}
protected Object readResolve() {
return getInstance();
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Cannot clone singleton");
}
}
Bill Pugh Solution (Best Practice)
Bill Pugh Solution is the best practice to implement the Singleton Design pattern. It uses static inner classes, ensuring lazy initialization and thread safety.
- Advantages – Best performance, thread-safe, and lazy-loaded.
- Disadvantages – Slightly complex.
I have defined a class named BillPughSingleton.java where I have written the code for the best way of implementing the Singleton Design pattern, which is thread-safe, lazy-loaded, and has the best performance.
public class BillPughSingleton {
private BillPughSingleton() {
if(null != BillPughSingletonHelper.INSTANCE) {
throw new RuntimeException("Use getInstance() method to create instance not using Constructor uisng Reflection.");
}
}
private static class BillPughSingletonHelper {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance() {
return BillPughSingletonHelper.INSTANCE;
}
protected Object readResolve() {
return BillPughSingletonHelper.INSTANCE;
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Cannot clone singleton");
}
}
I have written a main class named SingletonMasterclassApplication.java where all 5 types of implementations are called and tested by creating the instances.
Steps to run the application
The complete Run application steps are provided in this README.md file, but still, I am providing the steps to run points below.
- Clone the sprincavaj-designpattern application from the GitHub repository.
- Import the application as a Maven application, either in STS or Eclipse.
- Find the SingletonMasterclassApplication.java class.
- Right-click on the file and select Run As -> Java Application.
GitHub Code Link
Download the Source Code from GitHub
Common Problems Faced Implementing Singleton Pattern
Singleton Design Pattern Common Problems
Interview FAQs
Singleton Design Pattern Interview FAQs
Other Useful Links
Implementations of various components of Spring Boot