Blog

Best way for implementation of Singleton patterns for Java



There are four types of Design patterns in the category of Creational Design Pattern. Among the four different types, Java Singleton Pattern is one. When you look at it theoretically, Java Singleton pattern is very simple and easy to understand. But, the tough part is its implementation. There are a lot of concerns that come along with the implementation of Java Singleton Patterns.

Among the developers of Design patterns, the implementation of Java patterns has always been a debatable topic to deal with. Here we are going to discuss the principles of Singleton design patterns, the different ways to implement them, and also the best practices that can be taken into consideration for usage.

About Java Singleton:

  • The instantiation of a class is restricted in Singleton pattern and only a single instance of a particular class can exist in the virtual machine with java.
  • A global access shall be provided to an instance of the class by Singleton class.
  • Some design patterns like Builder, Abstract Factory, Façade, Builder, Prototype, etc is made use by Singleton design pattern.
  • For logging, caching, driver’s objects, and thread pool, Singleton pattern can be effectively taken into use.
  • In core java classes, the Singleton design pattern is used as well. For example,
    java.awt.Desktop, java.lang.Runtime.

More about Java Singleton Pattern:

There are many different approaches for implementing java Singleton patterns; but, the same concepts are applied to all of them. Some of these concepts are:

  • The instantiation of the class shall be restricted from other classes with the help of a private constructor
  • The instance of the class shall be returned with the help of Public static method
  • The only instance of the class can be implemented with the help of Private static variable of the same class

Let us discuss the different approaches to java Singleton pattern implementation.

Eager initialization

In eager initialization at the time of class loading, the instance of Singleton Class is fabricated. This is said to be the easiest way to establish a Singleton Class. But, the creation method has a drawback. However, clients mostly do not make use of this application.

Have a look at the Static Initialization singleton class.

package com.journaldev.singleton;

public class EagerInitializedSingleton {

private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();

//private constructor to avoid client applications to use constructor

private EagerInitializedSingleton(){}

public static EagerInitializedSingleton getInstance(){

return instance;

  }

}

If your singleton class does not require the usage of a vast number of resources, you can make use of this implementation. However, in almost all the scenarios, Singleton classes are fashioned for various resources including –Database connections, File System, etc. Therefore, every developer should avoid the instantiation approach until and unless the client specifically calls for it. Additionally, this method does not include any method for the handling of exceptions.

Lazy Initialization

The java singleton pattern implementation –Lazy-initialization method makes use of a global access method for the creation of an instance. Here we have jotted down the sample for the creation of singleton class with the help of this approach.

package com.journaldev.singleton;

public class LazyInitializedSingleton {

private static LazyInitializedSingleton instance;

private LazyInitializedSingleton(){}

public static LazyInitializedSingleton getInstance(){

if(instance == null){

instance = new LazyInitializedSingleton();

}

return instance;

}

}

Bill Pugh Singleton Implementation method

Before Java 5 came into existence, many of the developers faced several issues with the approaches and in certain scenarios, the instances would fail as well. Therefore, with Bill Pugh, a different approach was developed to create the Singleton class with the help of inner static helper class. The Bill Pugh Singleton implementation goes somewhat like:

package com.journaldev.singleton;

public class BillPughSingleton {

private BillPughSingleton(){}

private static class SingletonHelper{

private static final BillPughSingleton INSTANCE = new BillPughSingleton();

}

public static BillPughSingleton getInstance(){

return SingletonHelper.INSTANCE;

}

}

The private inner static class consists of the instance of a singleton class. Whenever the loading of Singleton class takes place, this class doesn’t get loaded on its own to the memory. The loading of this class takes place only when the developer calls for the getInstance method. This approach is the most widely used implementation of singleton class it as it doesn’t demand any form of synchronization. This method can be made use in many of the projects. Also, the added benefit is it is very easy to use.

To destroy Singleton pattern Reflection is used

All the above mentioned Singleton approaches can easily be destroyed with the help of Reflection. Let us understand the way it works.

package com.journaldev.singleton;

import java.lang.reflect.Constructor;

public class ReflectionSingletonTest {

public static void main(String[] args) {

EagerInitializedSingleton instanceOne = EagerInitializedSingleton.getInstance();

EagerInitializedSingleton instanceTwo = null;

try {

Constructor[] constructors = EagerInitializedSingleton.class.getDeclaredConstructors();

for (Constructor constructor : constructors) {

//Below code will destroy the singleton pattern

constructor.setAccessible(true);

instanceTwo = (EagerInitializedSingleton) constructor.newInstance();

break;

}

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(instanceOne.hashCode());

System.out.println(instanceTwo.hashCode());

}

}

If you notice or simply run the above-mentioned test class, you will get to know that the hashCode that is used is different for both the instances, which can be used in the destruction of Singleton pattern. It is a very powerful approach of java Singleton pattern and can be used in many of the frameworks including Hibernate and Spring.

Singleton and Serialization

In distributed systems, most of the times we need to make use of Serializable interface, which needs to be implemented in Singleton class so that it can be stored in the state of a file system. Whenever this file shall be required in the future, it will be retrieved from the file system without putting in much effort. Have a look as the singleton class implements here.

package com.journaldev.singleton;

import java.io.Serializable;

public class SerializedSingleton implements Serializable{

private static final long serialVersionUID = -7604766932017737115L;

private SerializedSingleton(){}

private static class SingletonHelper{

private static final SerializedSingleton instance = new SerializedSingleton();

}

public static SerializedSingleton getInstance(){

return SingletonHelper.instance;

}

}

However, the problem faced with serialized singleton class is whenever we try to deserialize it a new instance is created immediately. Let us understand it with the help of a single program.

package com.journaldev.singleton;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInput;

import java.io.ObjectInputStream;

import java.io.ObjectOutput;

import java.io.ObjectOutputStream;

public class SingletonSerializedTest {

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {

SerializedSingleton instanceOne = SerializedSingleton.getInstance();

ObjectOutput out = new ObjectOutputStream(new FileOutputStream(

"filename.ser"));

out.writeObject(instanceOne);

out.close();

//deserailize from file to object

ObjectInput in = new ObjectInputStream(new FileInputStream(

"filename.ser"));

SerializedSingleton instanceTwo = (SerializedSingleton) in.readObject();

in.close();

System.out.println("instanceOne hashCode="+instanceOne.hashCode());

System.out.println("instanceTwo hashCode="+instanceTwo.hashCode());

}

The output received when the above program is made to run is:

instanceOne hashCode=2011117821

instanceTwo hashCode=109647522

Therefore, the Singleton pattern is then destroyed. To surpass this situation and make complete use of serialization implementation, we need to make use of readResolve() method.

protected Object readResolve() {

return getInstance();

}

After you have made use of this method in java web development services, you will find that the hashCode of both the instances retrieved through the test program is just the same.