Singleton Design Pattern

The ‘Singleton design pattern’ is widely used in software development. Singleton design pattern restricts the instantiation of a class to one object.

The ‘Singleton design pattern’ is widely used in software development. Singleton design pattern restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. It uses static class methods and private constructors to control the creation of new class instances strictly.

The singleton design pattern ensures only one instance of a class is instantiated for the lifetime of the routine or the application. Every reference to the class refers to the same underlying instance. This is useful when exactly one object is needed to coordinate actions across the system.

Singleton class

  • Ensures you have at most one instance of a class in your application
  • Provides a global access point to that instance
  • Make use of a private constructor that prevents instantiation, a static method combined with a static variable.

The intent of the Singleton pattern

This pattern intends to

  • Ensure that only one instance of a class is created.
  • At the same time, a (global) “point of access” must be provided so that any client may have access to the single instance

Singleton with example

Let’s look at what a singleton can look like using the example below.

public final class Singleton {                                               
private static Singleton singletonObject = null;
//private constructor so that no one creates object with new operator
private Singleton () {
  }       
public static Singleton getInstance () {

if (singletonObject == null)  {  
singletonObject = new Singleton ()
  
}   
  return singletonObject;
  } 
} 
  • To create a Singleton class, you add a private class level static variable with the data type of the class itself (line #2)
  • Next, you mark the class constructor as private to disable the Java new keyword (Line #4). The private constructor ensures that the class can be initialized by itself
  • Finally, you add a method called (by convention) getInstance( ). (Line #6)
  • The getInstance( ) method checks to see if the static class variable is null, and if it is null, it creates an instance of the class and stores the reference in the class variable, and returns the reference to the caller (Line #8, 9)
  •  If the static class variable is not nullgetInstance() returns the existing reference to the single existing instance of the class to the caller (Line #12)
  • In this way, all callers to getInstance( ) get the same reference to the single instance of the class.
  • The rest of the class can be written just like a regular class, and the variables and methods are accessed via the instance reference in the calling class.

Why use a singleton pattern

The singleton design pattern is very useful. Sometimes, you want to make sure only one instance of the class is instantiated and that your application only uses that instance. That’s the primary and only goal of the singleton pattern.

Using the singleton design pattern when having more than one class instance would cause a problem, or it wouldn’t be logical.

  • The logging class: When logging classes are created, they have to provide a global logging access point in all the application components without being necessary to create an object each time a logging operation is performed.
  • Reading a configuration file: The content of an application’s configuration file is shared across the entire application context. Hence there is no need to load this file more than once unless it changes frequently. A singleton class is helpful for this scenario since we avoid the loading of properties more than once every time a class needs to access that resource.

How to create a singleton object in Java

Some of the ways to develop singleton objects are

  • Singleton with eager instantiation
  • Lazy loading
  • Using enum

Singleton with Eager Instantiation

According to the principle of eager instantiation, the object should be created and ready to use. Mostly it is done on the system startup.

public class Singleton {                                               
private static Singleton instance = new Singleton ();
//private constructor so that no one creates object with new operator
private Singleton () {
  }       
public static Singleton getInstance () {

  } 
} 

The above method works fine. But the instance is created (Line #2) irrespective of whether it is required in runtime. Use this method only when the Singleton class is light, and you can live with it being unused.

Singleton with lazy initialization

Here we are initializing the Singleton instance in a lazy way. We get it initialized when someone needs it; otherwise, it’ll never be initialized.

public final class Singleton {                                               
private static Singleton singletonObject = null;
//private constructor so that no one creates object with new operator
private Singleton () {
  }       
public static Singleton getInstance () {

if (singletonObject == null)  {  
singletonObject = new Singleton ()
  
}   
  return singletonObject;
  } 
} 

In the above example, we can see we aren’t instantiating Singleton eagerly. On the first invocation, the above method will check whether an instance is already created using the instance variable. If there is no instance variable, i.e., the instance is null, it will create an example and return a reference. If the instance is already created, it will simply return the instance’s reference.

Singleton with Double Check and Locking Instantiation

The main problem with the lazy initialization method is that it is not thread-safe. If we have two threads, T1 and T2, which invoke the getInstance( ) method simultaneously, the execution sequence creates two objects for Singleton.

This error can be solved using double-checked locking. This principle tells us to recheck the instance variable in a synchronized block.

public final class Singleton {                                               
private static volatile Singleton singletonObject = null;
//private constructor so that no one creates object with new operator
private Singleton () {
  }       
public static Singleton getInstance () {

if (singletonObject == null)  {  
synchronized (singleton.class){
//double check
if (singletonObject == null){
singletonObject = new singleton();
   }
}  
    
}  
  return singletonObject;
  } 
} 

One thing to keep in mind with this pattern is that the field needs to be volatile to prevent cache incoherence issues

Related Articles