Creational Design Pattern: Singleton

The Singleton pattern is one of the quirkiest and most trivial patterns in existence. This pattern was created to fulfil the need for a single, one-time instantiation of an object that is shared among multiple components.

Photo by Vijayalakshmi Nidugondi on Unsplash

This article is the first in a series exploring design patterns using the Java programming language. The goal of this series is to help readers develop a solid understanding of design patterns while also sharing real-world examples from actual codebases that make use of these patterns.

In this article, we’ll be discussing the Singleton pattern.

Symbols for better navigation:

🤔 Hypothetical Scenario/Imagination

⚠️ Warning

👉 Point to note

📝 Common Understanding

Singleton Pattern

Full Singleton Pattern explanation in video format

The Singleton pattern is one of the quirkiest and most trivial patterns in existence.

This pattern was created to fulfil the need for a single, one-time instantiation of an object that is shared among multiple components.

🤔 A common way to implement the Singleton pattern is to have a global variable in a class, which can be declared as public and static, allowing classes in other packages to access it.

Java
public class MyBigApplication {
  public static class Hello { // my global single class 
    // declare only static variables and methods with synchronization
  } 
  ...
}

⚠️ However, this introduces many downsides. Security is one of those, but more importantly, the global variable declaration is wasting valuable resources.

So what’s the singleton pattern in essence?

👉 Singleton pattern is a pattern that restricts the creation or instantiation of an object more than one time.

Why do we need such a pattern, though?

🤔 Imagine if you want to create an object(runtime instance) that has to be shared among multiple classes, including its data(state), which should be centralised, i.e. single point of access, then you’ll need a singleton.

👉 A common example of this is the Thread Pool in Java, which is a singleton giving access to pools to all the running and idle threads in the JVM.

👉 One more example is LogManager, which is responsible for logging all the activities of the class. We do not require more than one instance of the LogManager as they might interfere in the activity of each other’s resources and we might end up having redundant log data.

Other fine examples of Singleton can be Database connections, File Systems, Locking system in an operating system, etc.

Recipe to cook a Singleton

Singleton as a concept is simple, but the implementation can be trivial. Once you’ve figured out that you will need a singleton, here’s how you can write a single for yourself.

Any class can be converted to a singleton by following these steps:

  1. Declare the constructor of the class private — it should not contain parameters, as the Singleton pattern does not promote variable constructors of object instantiation. For this purpose, Factory or Builder is more suitable.
  2. Declare a private static variable of the same type as the class, name it INSTANCE.
  3. Define a method with public static with return type as the same method as the class name. This method should return the INSTANCE variable declared as private. If the INSTANCE variable is not initialised, then we first initialise it and then return it.

That’s it! 🥳

Let’s say now I create a class Hello as follows.

Java
class Hello {
  public void sayHello() {
    System.out.println("Hello, World");
  }
}

Now I’ll convert this class to a singleton according to the steps I mentioned previously.

Java
class Hello {
  private Hello() {} // no arguments!
  private static Hello INSTANCE; // only declaration
  public static Hello getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Hello(); // if not initialized
    }
    return INSTANCE;
  }
  public void sayHello() { // same as before
    System.out.println("Hello, World");
  }
}

😮 So now we have a class which can only be instantiated once.

The UML of the Singleton is now extremely simple.

Singleton Class Diagram

With this, we can use the Singleton class as follows.

Java
class SingletonDemo {
  public static void main(String[] args) {
    Hello myHelloSingleton = Hello.getInstance(); // single instance
    myHelloSingleton.sayHello();
  }
}

But! 🤔

We have introduced a problem with the current implementation, viz., race condition during multi-threading.

Quirkiness in Singleton Implementation

Let’s suppose two threads are trying to access the singleton via getInstance().

If both try to access the instance at the same time, they’ll end up creating two different instances in the memory, and the whole purpose of the Singleton being Single is defeated.

To prevent this issue, the simplest way is to declare the getInstance() method synchronised.

Java
class Hello() {
  private Hello() {}
  private static Hello INSTANCE;
  public synchronized static Hello getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Hello();
    }
    return INSTANCE;
  }
  public void sayHello() { 
    System.out.println("Hello, World");
  }
}

Awesome!

But again! 😪

Do we really need to synchronise every time a thread calls the getInstance() method?

The synchronisation is only needed once during the instanciation of the Hello class, so keeping the synchronise declaration is levying too much expense on the resources.

So, to prevent that, we can simply do Eager instantiation.

Java
class Hello {
  private Hello() {}
  private static Hello INSTANCE = new Hello(); // Eager Instantiation
  public synchronized static Hello getInstance() {
    return INSTANCE;
  }
  public void sayHello() { 
    System.out.println("Hello, World");
  }
}

Alright! Race condition fixed, Expensive synchronisation fixed …

But wait! At what cost!? 🤕

The eager instantiation always creates the instance of the class when the class is loaded into memory, right?

If other classes do not need the Hello class, then we are simply occupying the memory with a worthless instantiation of Hello.

This is painfully costly when the Hello class is too large, for example, what if Hello were running an instance of PostgreSQL Database within it?

We never know!

So, how do we solve this problem? 🤔

Enters … Lazy Instantiation.

Java
class Hello {
  private Hello() {}
  private static class LazyLoader {
    private static Hello INSTANCE = new Hello(); // Lazy Instantiation
  }
  public synchronized static Hello getInstance() {
    return LazyLoader.INSTANCE;
  }
  public void sayHello() { 
    System.out.println("Hello, World");
  }
}

In Lazy instantiation, we are wrapping the static variable in a static class. So even if the main class, i.e. Hello, loads into the memory, the instance is not initialised unless the program invokes or loads the LazyLoader class in the memory!

And with that, we have solved everything that the Singleton pattern would ever need in terms of efficient resource utilisation:

  1. Prevention of race conditions during multi-threading.
  2. Less expensive than synchronisation.
  3. On-demand instantiation of the resource.

👉 One more hack in the Java Programming language, which can be used for creating a Singleton, is the use of the Enum class.

Java
public enum Hello {
    INSTANCE;

    public void sayHello() {
        System.out.println("Hello, World");
    }
}

Enum classes in Java, by default, can only be instantiated once during runtime.

📝 However, the usage of Enum is just an implementation detail and is left to the developer’s wisdom to be selected as a way to implement the singleton for their particular use case.

Real-World Use Case of Singleton

Here is an example from the real-world code where they have used a Singleton.

LogManager in Java in JDK employs the singleton technique to prevent more than one instantiation.

As it stated in the comments, “It is non-public as it is intended that there can only be one LogManager object”.

Code Capture of Java JDK LogManger

Up Next in the series

Builder Design Pattern

Subscribe to my newsletter today!

Share it on

2 Comments

  1. It’s a pity you don’t have a donate button! I’d without a doubt donate to this excellent blog! I suppose for now i’ll settle for book-marking and adding your RSS feed to my Google account. I look forward to fresh updates and will share this website with my Facebook group. Chat soon!

  2. naturally like your web site however you need to take a look at the spelling on several of your posts. A number of them are rife with spelling problems and I find it very bothersome to tell the truth on the other hand I will surely come again again.

Leave a Reply

Your email address will not be published. Required fields are marked *