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.

public class SampleClass {
    // this is instantiated eagerly
    private static SampleClass singleton = new SampleClass();

    private SampleClass() {
    }

    public static SampleClass getSampleClass() {
        // check has been removed
        return singleton;
    }
}
Eagerly instantiated Singleton

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.

public class SampleClass {
    // volatile is used to make the object thread safe
    private volatile static SampleClass singleton;

    private SampleClass() {
    }

    public static SampleClass getSampleClass() {
        if (singleton == null) {
            synchronized (SampleClass.class) {
                if (singleton == null) {
                    singleton = new SampleClass();
                }
            }
        }
        return singleton;
    }
}
Double Check locking based Singleton

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 as volatile 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 a synchronized 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 still null 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.

public enum SampleClass {
    SINGLETON;
}
Singleton using an enum

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.