Understanding Singleton Pattern

Jalitha Dewapura
Design Patterns with Java
4 min readMay 23, 2021

--

In the previous blog post, we walked over to the overview of design patterns. If you haven’t read the previous post yet, I suggest you read that before proceeding with this article.

Singleton pattern is under creational patterns that are used to control the object creation. Most of the engineers say that “Singleton is nothing. It just one instance”. But we need to understand one instance per what?

Actually, Singleton is one instance per container. As a java developer, one instance per JVM. In one of my previous articles about JVM, I explained all the instances are stored in the heap area. Since a heap area is created for a JVM, the instance can be created per JVM.

Before using this design pattern, you need to ensure that you want to control the object creation by introducing a single instance. Most of the developers misuse the singleton pattern. Because of the simplicity of this pattern. But you should remember that unit testing is really hard with the Singleton pattern. Furthermore, you should not pass any argument to the singleton class constructor. If you really need to pass an argument, you should work with the Factory pattern instead of the Singleton pattern.

As I explained earlier, the Singleton pattern avoids creating multiple instances. Instead, it introduces a method to access a single instance through the application.

Let’s see some common examples for the Singleton pattern.

  • Creating the database connection — you all know that the database connection should be created the very first time it is used. Therefore, Singleton is perfect for it.
  • Creating some services — if a service is used throughout the application and it should work with a single instance, the Singleton is good to use.

Implementing a Singleton class

As you understand, the singleton class must avoid creating multiple instances. Therefore, we need to create a private constructor. Then we have to give a solution to access the instance. We all know, the static fields and methods are accessible without creating an instance. So, we create a static getter method to access the single instance.

UML diagram,

Let’s see some coding examples,

Assume we need to implement a mailService that can be accessed throughout the application. There are two methods to enable and disable the mailService. This instance should be created the very first time it is used. Let’s see how to implement it.

First of all, I have declared a private variable called mailService. It is used to initialize the instance when it is created. Before creating an instance, we need to check that whether the mailService variable is null or not. If it is null, then create a new instance and initialize in the mailService variable. As I explained, the mailService() constructor is private. So it can be accessed within the class.

Let’s see how to use this instance in the application.

See the output,

The output of the Application

You can see the both m1 and m2 have stored the same memory address. It is working as we expected. But if you think deeply, you will understand that it is not thread-safe. As a solution, we can implement a double-checking singleton class. Let’s see it.

Double-Checking Singleton

It is a little tricky implementation by using the synchronized keyword. Let’s see the code first.

Assume two threads try to create the instance simultaneously. As you see in line number 15, I used a synchronized block to hold the second thread. After the first thread is completely created the execution, the second thread goes into the synchronized block. Then it checks again whether the mailService is null or not. This time it is not null. Because the first thread created the instance.

So, you may have some confusion about why I didn’t use the synchronized keyword on the method declaration. It is not a good practice. Because it may be caused performance loss by blocking the whole method. As a good programming practice, you should block a few particular lines by the synchronized block.

--

--