The singleton pattern is a software design pattern which restricts the instantiation of a class to one object. This is useful when exactly one instance of a class is needed to coordinate actions across the system. For an example, a single DB connection shared by multiple objects as creating a separate DB connection for every object may be costly. The term comes from the mathematical concept of a singleton.
Definition
The singleton pattern is a design pattern that ensures at most one instance of a particular class is ever created in the application.
More examples of the Singleton
Project Configuration
The class that reads project configuration should be made Singleton by reads once and holds on application Cache and global access to all classes in the application.
Application Log
Logger must be initialized once and can be used everywhere in the application.
Analytics and Reporting
If you are using some kind of data analysis tool like Google Analytics, you will notice that they are designed to be a singleton. It initializes once and being used everywhere for each user action.
How to achieve Singleton property
1. Hide the constructor of the class (make the constructor private).
2. Define a public static operation (getInstance()) that returns the sole instance of the class.
/**
* Basic singleton design pattern implementation in Java
* @author rajesh.dixit
*/
class Singleton {
private static Singleton INSTANCE;
/** 1. Hide the constructor. */
private Singleton() {
}
/**
* Returns the sole instance of the class.
* @return instance of the class
*/
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Singleton and Thread Safety
Two instances of Singleton class will be created if the getInstance() called simultaneously by two threads. We can make the make getInstance() method synchronized to ensure that no two threads can be entered into getInstance() method at the same time.
public static synchronized Singleton getInstance() {
/* Lazy initialization, creating object on first use */
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
Singleton and Early Initialization
Using early initialization we will initialize upfront before our class is being loaded. This way we don’t need to check for synchronization as it is initialized before being used ever.
class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {
}
/**
* Returns the sole instance of the class.
* @return instance of the class
*/
public static Singleton getInstance() {
return INSTANCE;
}
}
Singleton and Object Cloning
Cloning is used to create a copy of the object at any instance original object by implementing java.lang.Cloneable interface and override clone() method from Object class.
To prevent cloning on singleton object, throw CloneNotSupportedException exception explicitly from the clone() method.
Singleton and Serialization
Java Serialization allows converting the state of an object into the stream of bytes to store or transfer. Deserialization used to convert byte stream into. If a singleton class desterilized, it will end up creating duplicate objects.
To resolve this issue, we need to include readResolve() method in our class which will be invoked before the object is de-serialized. We will return INSTANCE from readResolve() which will ensure a single instance of the Singleton class exists in the application.
import java.io.Serializable;
class Singleton implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private static volatile Singleton INSTANCE;
private int value;
/** Private Constructor prevents any other class from instantiating. */
private Singleton() {
}
public static synchronized Singleton getInstance() {
/* Lazy initialization, creating object on first use */
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
/** restricts another object creation while de-serialization. */
protected Object readResolve() {
return getInstance();
}
/** restricts cloning of object */
@Override
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public void display() {
System.out.println("Hurray! I am display from Singleton!");
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
Example of Singleton pattern in core libraries
Creational methods return the same instance again and again.
java.lang.Runtime#getRuntime()
java.awt.Desktop#getDesktop()
java.lang.System#getSecurityManager()