The Singleton Pattern
A single instance of a class with a global reference. [creational pattern]
There are scenarios where only a single object instantiation is necessary, such as for caches and objects used for logging. In such cases, instantiating more than one could lead to various issues, including incorrect program behaviour, excessive resource usage, and inconsistent results.
A class can be instantiated any number of times by using just the new keyword with the constructor. How can we ensure that only a single object is allowed to be created for a class?
public class MyClass {
private MyClass() {}
}
public class MyClass {
public static MyClass getInstance() {}
}
public class MyClass {
private MyClass() {}
public static MyClass getInstance() {
return new MyClass();
}
}
Let’s make a slight adjustment to the above approach to guarantee a single instance of the MyClass class.
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other methods -> singleton class is same as any other class.
}
The Singleton Pattern ensures that a class has only one instance and provides a global point of access to it.
领英推荐
Dealing with Multithreading
Alright, now with the Singleton class, we ensure the existence of only one instance of the class. However, in a multi-threaded environment, does this functionality still hold, and is it truly thread-safe?
Using the synchronized keyword can ensure that only one thread at a time can execute a particular block of code.
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other methods -> singleton class is same as any other class.
}
Move to an eagerly created instance rather than one created lazily.
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static synchronized Singleton getInstance() {
return uniqueInstance;
}
}
Double-checked locking to reduce to use of synchronization in getInstance()
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
Singleton with enums
public enum SingletonEnum {
INSTANCE; // The single instance of the SingletonEnum
// Add other methods or fields as needed
public void doSomething() {
System.out.println("SingletonEnum is doing something.");
}
}
public class SingletonExample {
public static void main(String[] args) {
// Access the singleton instance
SingletonEnum singleton = SingletonEnum.INSTANCE;
// Use the singleton instance
singleton.doSomething();
}
}
Referenced from the book ‘Head First Design Patterns’ by Eric Freeman, Elisabeth Robson, Kathy Sierra, and Bert Bates.