Why did we start using the Singleton Pattern?
Singleton is a creational design pattern that lets you ensure that a class has only one instance while providing global access to this point.
The pic is sarcastic, do not take it personally, but the characteristics match the characteristics of our Singleton too, so its a win win🙂
Why we need it
It all depends on the need for it, which can be any of these
- Say you are establishing a database connection, you need not establish multiple connections, one would just do fine.
- Same with the File reader
- Same with data processors.
Challenges
- It is not easy to create it with a regular constructor because a constructor call must always return a new object by design.
- Just like a global variable, the Singleton pattern lets you access some object from anywhere in the program. However, it also protects that instance from being overwritten by other code.
- You don’t want the code that solves problem #1 to be scattered all over your program. It’s much better to have it within one class, especially if the rest of your code already depends on it.
Solution
- Make the default constructor private, to prevent other objects from using the
new
operator with the Singleton class. - Create a static creation method that acts as a constructor. Under the hood, this method calls the private constructor to create an object and saves it in a static field. All following calls to this method return the cached object.
- Since it is static, whenever out static method is called there is no action performed and the same object is returned back.
Peek
We are going to create a Singleton class with a method that can give an instance. As it is static, we need not do any initialization of the object.
Pseudocode
class Singleton {
private static instance: Singleton;
private constructor() {}
public static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
public someMethod() {
// ...
}
}
Uses
- Use is when there is absolutely no need to instantiate the object and there is no dynamic nature involved in its functionality.
Use the Singleton pattern when you need stricter control over global variables
Unlike global variables, the Singleton pattern guarantees that there’s just one instance of a class. Nothing, except for the Singleton class itself, can replace the cached instance
Implementation steps
- Add a private static field to the class for storing the singleton instance.
- Declare a public static creation method for getting the singleton instance.
- Implement “lazy initialization” inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.
- Make the constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.
- Go over the client code and replace all direct calls to the singleton’s constructor with calls to its static creation method.
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public void someMethod() {
}
}
//synchronized helps to avoid multiple creations in Multithreaded environment
Cons
It Violates the Single Responsibility Principle. The pattern solves two problems at the time. The pattern requires special treatment in a multithreaded environment so that multiple threads won’t create a singleton object several times. It may be difficult to unit test t because many test frameworks rely on inheritance when producing mock objects.
So it is completely up to the user to use it properly so that there won’t be any unexpected scenarios.