dcsimg
October 19, 2019
Hot Topics:

Implementing Singleton Patterns in Java

  • February 4, 2019
  • By Manoj Debnath
  • Send Email »
  • More Articles »

The singleton pattern guarantees that only one object with a global access point can be created in a given instance of time. This is one of the most commonly used techniques in object-oriented programming. Although it is simple, perhaps the simplest from the class design point of view, there are subtle issues that one must understand before trying to implement them. This article delves into exploring this pattern citing Java code examples.

Overview

There is situation where a system should allow only one object of a class to be in memory at a given point of time. This means that, when the program instantiates that object, the program should not be allowed to create additional objects of that class. For example, in a system that connects to a database uses only one object to manage the database connection. This ensures that other objects cannot initialize unnecessary connections which would slacken the overall performance of the system due to multiple instantiations. This can very easily be tested by creating multiple JDBC connections and observing the performance. The performance is bound to suffer or slow down noticeably. A singleton pattern essentially guarantees that a system creates only one instance of a class.

The Singleton Pattern

Using a singleton pattern is a standard technique to ensure that one and only one object is instantiated for a given class. It is one of the twenty-four design patterns discussed by the Gang of Four. The idea is to address the issues such as instantiating a single instance of a class, accessing the sole instance of a class, or controlling the class instantiation process. The key technique to achieve this is by concealing the constructor with a private modifier and supplying a method that applies checks and validation to ensure that only one instance of the class is created.

This is simple yet effective to deliver the need. In fact, by applying the same principle we can control the exact number of instances created of a class, not restricted to a single instance only. But, here we focus only on the single instance.

Using the Singleton Pattern

It is not hard to find a situation where we actually need only one instance of a class in memory. Multiple objects can ruin the cause or create havoc in the performance of a running application. In object-oriented programming, a running application typically has a number of objects in the memory, interacting and playing a crucial part in the execution. But, when implementing thread pools, caches, dialog boxes, or objects that take care of preferences and registry settings, database connection, logging, objects acting as a device driver to peripheral devices or graphics card and so forth are all situations where we want a single instance of an object running; otherwise, it would create a lot of problems like resource clogging, memory overload, and many other inconsistent behaviors. This is exactly where we need to identify the classes that are suitable for implementing a singleton pattern and design them accordingly.

Implementing the Singleton Pattern

Here is a quick implementation of the pattern.

public final class Singleton {
   private static final Singleton singleInstance =
      new Singleton();
   private Singleton(){
   }
   public static Singleton getInstance(){
      return singleInstance;
   }
}

public class TestSingleton {
   public static void main(String[] args){
      Singleton s1;
      Singleton s2;
      s1 = Singleton.getInstance();
      s2 = Singleton.getInstance();
      if(s1 == s2){
         System.out.println("References to same
            Singleton object");
      }
   }
}

The Singleton class is declared as final so no subclass can be created. This restricts multiple instantiation even by sub classing this class. The constructor is declared private; as a result, only the Singleton class can create a Singleton object using this constructor. The static reference to the Singleton object invokes the private constructor and delivers only one instance of the class. On invocation of the getInstance() method, only the reference copy of the object is received.

Here, we use a simple test by creating another class, called TestSingleton. This class declares two reference Singleton objects and invokes the getInstance() method. Then, we compare the two references to ensure that they actually refer to same runtime instance and not two distinct objects.

Sometimes, we need an implementation that creates an instance only when the first static method is invoked and not prior to that. In the preceding example, the objects get created statically; the getInstance() method has the role of simply returning the references. In this case, we want to create the object on first invocation, called lazy initialization. Also, we want the invocation to be thread-safe; otherwise, it can result in a strange erratic behavior or memory leaks resulting in JVM crashes. Here is the example to achieve that.

public final class Singleton {
   private static volatile Singleton singleInstance =
      null;
   private Singleton(){
   }
   public static Singleton getInstance(){
      if (singleInstance == null) {
         synchronized(Singleton.class) {
            if (singleInstance == null) {
               singleInstance = new Singleton();
            }
         }
      }
      return singleInstance;
   }
}

public class TestSingleton {
   public static void main(String[] args){
      Singleton s1;
      Singleton s2;
      s1 = Singleton.getInstance();
      s2 = Singleton.getInstance();
      if(s1 == s2){
         System.out.println("References to same
            Singleton object");
      }
   }
}

A singleton also can be implemented using Enum. In fact, is is often better to use Enum when possible instead of classes to implement a singleton pattern. JVM guarantees that only one instance ever be created from a singleton Enum.

public enum SingletonEnum {
   SINGLEINSTANCE;
   public void someMethod(){
      // ...
   }
}

public class TestSingleton {
   public static void main(String[] args){
      SingletonEnum s1;
      SingletonEnum s2;
      s1 = SingletonEnum.SINGLEINSTANCE;
      s2 = SingletonEnum.SINGLEINSTANCE;
      if (s1 == s2){
         System.out.println("References to same
            Singleton object");
      }
   }
}

Conclusion

As always, user discretion is the key to good design because an improper use of the singleton pattern may lead to other issues; it is very difficult to test a singleton if it performs complex and heavyweight operations. A better suggestion is to use a dependency injection framework to construct a single object. A singleton works best in a situation such as creating dialog boxes in a GUI application or when there is little chance to have concurrent users. The singleton pattern, although useful, is notorious for creating performance bottlenecks in large scalable applications.







Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.


Thanks for your registration, follow us on our social networks to keep up-to-date