Design Patterns - Singleton Pattern
Quite often you will require an object that you need exactly one instance of and no more than that. This can be for say caches or even a factory that has a single client (we talked about factories in our previous post which you can check out here). This is where the Singleton Pattern is helpful. The term comes from mathematical "singleton" which is used to define a unit set or a set with only one single element for example { 1 }
is a singleton set with only the element 1
in it.
Here is how Wikipedia defines the term singleton pattern
In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one "single" instance. This is useful when exactly one object is needed to coordinate actions across the system.
Now the ardent among you readers may already be noting that we might be violating some of the principles of object oriented design. We are preventing re-usability of our code as well as preventing dependency injection. These are some trade offs of this techniques which is why many consider this to be a design anti-pattern.
An anti-pattern is a common response to a recurring problem that is usually ineffective and risks being highly counterproductive.
How to implement it?
The first question that will come to your mind would be how to even prevent multiple instantiations of the same object? Cause normally, as long as the new
keyword is used, the object will be instantiated! The solution? A private
constuctor.
public class SampleClass {
private SampleClass() {
}
}
While this may seem counter-intuitive, this is perfectly legal Java code. However, due to the private nature of the SampleClass
constructor an outside object will not be able to instantiate a class using the new
keyword. The only methods and variables that can access the constructor will be the ones that are members of the class itself. Then how to do we create a single instance of the object? Enter the static
keyword.
public class SampleClass {
private SampleClass() {
}
public static SampleClass getSampleClass() {
return new SampleClass();
}
}
So first we created a getter function getSampleClass()
that is static. This means that we will be able to call it without having an instance of the class by just using SampleClass.getSampleClass()
. This function would invoke the constructor, create an object and return it. However, we have yet to enforce our goal of a single instance creation. That would be done by simply adding a check.
public class SampleClass {
// the one and only instance the class manages
private static SampleClass singleton;
private SampleClass() {
}
public static SampleClass getSampleClass() {
// check singleton is already initialized
if (singleton == null) {
singleton = new SampleClass();
}
return singleton;
}
}
We added a further check to prevent multiple object creation. So far we have achieved the following
- Each singleton class manages its own instantiation using a private constructor that is not accessible to code outside the class definition.
- Every client that wishes to use the singleton object must rely on the getter method that uniquely returns the object.
Problems with Multi-threading
So far we still deal with one main issue. How do we deal with multi-threaded programs? Even though there's is a check for null
in a multi-threaded program two threads may invoke the class in such a way that two programs are created. One way to deal with it is using an eager instantiation.
We have moved the creation of the object to the top, hence JVM would create the object at the very start preventing multiple object creation in the first place. But what if we are not sure if we even need the object in the first place? It would be an unnecessary burden if we are not sure whether the object is needed and we would like to have the benefits of lazy object creation while not having the headaches of multi-threading. We go with something known as double check locking.
There is a lot going on here, so let's break it down bit by bit.
- First we start of marking the
singleton
member variable asvolatile
which prevents multiple threads from creating their own copies of the object and only a single copy of the object exists in memory and all threads access this one single class. - We then add the first check which checks if
singleton
has been created. If it's not created we enter asynchronized
block. What this keyword does is, the threads only enter this block one at a time in a synchronized manner unlike an asynchronous mechanism. - Once we enter the synchronized block we further check if the
singleton
object is stillnull
and only then we create an instance.
This is how we can thread safely create a singleton object in a multi-threaded program. Now there is a caveat to this method and that is due to memory issues with older JDKs, this method only works post JDK 1.5.
Enums
Now, while the above are good ways to understand the workings behind how the pattern itself works, in the actual implementation, using an enum
would prove to be far superior.
Closing Thoughts
This concludes the fourth pattern that we are covering in this series of commonly used Design Patterns. There's a lot more ground to cover before we have a complete object oriented toolbox.
As always I would love to hear your feedback on this post, feel free to write to me at akshay [at] akshayprabhu [dot] dev or tweet at my twitter handle @akshaprabhu200.