Java Singleton Design Pattern

Java has several design patterns Singleton Pattern being the most commonly used. Java Singleton pattern belongs to the family of design patterns, that govern the instantiation process. This design pattern proposes that at any time there can only be one instance of a singleton (object) created by the JVM.

  • Intention :

    1. Ensure a class has only one instance, and provide a global point of access to it.

    2. Encapsulated "just-in-time initialization" or "initialization on first use".

  • Problem :

      Application needs one, and only one, instance of an object. Additionally, lazy initialization and global access are necessary.

  • Requirements to create a singleton object in Java :

    1. Provide a default Private constructor.

    2. Create a Method for getting the reference to the Singleton Object.

    3. Make the Access method Synchronized to prevent Thread Problems.

    4. Override the Object clone method to prevent cloning.

  • Step 1 : Create a class Singleton.

  • package com.javabykiran.singleton;
    
        public class JbkSingletonEx {
        private static JbkSingletonEx js;
        private JbkSingletonEx() {
    	super();
        }
    
        synchronized public static JbkSingletonEx getSingltonObject() {
    	if (js == null) {
                js = new JbkSingletonEx();
    	}
    	return js;
        }
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    }
  • In given Program all the specified requirement for singleton pattern is satisfied.


  • Step 2 : Make default constructor private.

  • package com.javabykiran.singleton;
    
        public class JbkSingletonEx {
            private static JbkSingletonEx js;
            private JbkSingletonEx() {
                super();
            }
        }
    

  • Step 3 : Create a Method for getting the reference to the Singleton Object and make it as synchronized.

  • synchronized public static JbkSingletonEx getSingltonObject() {
    
        if (js == null) {
            js = new JbkSingletonEx();
        }
        return js;
    }
    
  • Note :

    1. We write a public static getter or access method to get the instance of the Singleton Object at runtime. First time the object is created inside this method as it is null. Subsequent calls to this method returns the same object created as the object is globally declared (private) and the hence the same referenced object is returned.

    2. It could happen that the access method may be called twice from 2 different classes at the same time and hence more than one object being created. This could violate the design patter principle. In order to prevent the simultaneous invocation of the getter method by 2 threads or classes simultaneously we add the synchronized keyword to the method declaration.

    SingletonObjectDemo clonedObject = (SingletonObjectDemo) obj.clone();

  • Step 4 : Override the Object clone method to prevent cloning.

    1. We can still be able to create a copy of the Object by cloning it using the Object’s clone method. This can be done as shown below:

    2. This again violates the Singleton Design Pattern’s objective. So to deal with this we need to override the Object’s clone method which throws a CloneNotSupportedException exception.

    @Override
    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
    

  • Step 5 : Create class SingletonObjectDemo to test the Singleton pattern.

  • package com.javabykiran.singleton;
    
    public class JbkClient {
        public static void main(String[] args) {
    	JbkSingletonEx jbk = null;
    
    	jbk = jbk.getSingltonObject();
    
    	System.out.println(jbk);
    
    	JbkSingletonEx jbk1 = null;
    
    	jbk1 = jbk1.getSingltonObject();
    
    	System.out.println(jbk1);
        }
    }
    
  • Run the given class as java Application and we will get the output.

  • You can see that same address is get printed each time.

  • Java Singleton Design Pattern

  • Note :

    To prove that only one object has been created for the Singleton class and if we try to make another one in JbkClient class what will happen?

  • Another object cannot be created in Singleton Design Pattern

  • This proves that another object cannot be created for the Singleton Design pattern.

Sometimes in distributed systems, we need to implement Serializable interface in Singleton class so that we can store it’s state in file system and retrieve it at later point of time. Here is a small singleton class that implements Serializable interface also.

  • Step 1 : Create a Singleton class with Serialization.

  • package com.javabykiran.singleton.serialization;
    import java.io.Serializable;
    
    public class JbkSingletonSerializable implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private JbkSingletonSerializable() {
    
        }
    
        private static class SingletoneHelper {
    	private static JbkSingletonSerializable js = new JbkSingletonSerializable();
        }
    
        public static JbkSingletonSerializable getInstance() {
    	return SingletoneHelper.js;
        }
    }
    

  • Step 2 : Create a class to test that serialized singleton object persist or not.

  • package com.javabykiran.singleton.serialization;
    
    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 JbkSingltonSerializeTest {
        public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
    
    	JbkSingletonSerializable instance1 = JbkSingletonSerializable.getInstance();
    
    	ObjectOutput out = new ObjectOutputStream(new FileOutputStream("fileName.ser"));
    	out.writeObject(instance1);
    	out.close();
    
    	ObjectInput in = new ObjectInputStream(new FileInputStream("filename.ser"));
    	JbkSingletonSerializable instance2 = (JbkSingletonSerializable) in.readObject();
    	in.close();
    
    	System.out.println("Instance1 hashcode " + instance1.hashCode());
    	System.out.println("Instance2 hashcode " + instance2.hashCode());
    
        }
    }
    

  • Step 3 : Run the Test Program to see output

  • Java Singleton Design Pattern Program output

  • This proves that singleton Object is not preserved while Deserialization, because both of the instances have different hashCode.

  • So it destroys the singleton pattern, to overcome this scenario all we need to do it provide the implementation of readResolve() method.

  • package com.javabykiran.singleton.serialization;
    
    import java.io.Serializable;
    public class JbkSingletonSerializable implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private JbkSingletonSerializable() {
    
        }
    
        private static class SingletoneHelper {
    	private static JbkSingletonSerializable js = new JbkSingletonSerializable();
        }
    
        public static JbkSingletonSerializable getInstance() {
    	return SingletoneHelper.js;
        }
    
        protected Object readResolve() {
    	return getInstance();	
        }
    }
    

  • After this you will notice that hashCode of both the instances are same in test program.
  • Java Singleton Design Pattern Program output

  • This proves that the Singleton object has been serialized with both the instances having same hashCode.