Monday, September 19, 2011

How to create Singleton design pattern using Java


Singleton pattern is a design solution where an application wants to have one and only one instance of any class, in all possible scenarios without any exceptional condition

Before seeing  Some of the techniques which are commonly used to make a class Singleton, first let's familiarize with some common steps that each of these techniques uses:

   1.Make the constructor private-

 Other classes can instantiate any object of the class by using the new keyword. Therefore default constructor of the class needs to be made private.The new keyword can then be used from within the class only.

public class SingletonDemo{
 private SingletonDemo() {}
}

   2. One method to get the instance- Though we've made the constructor private so that other classes can’t instantiate but we should have one method to get the only one instance.
public class SingletonDemo
{
    private static SingletonDemo instance;
 
    private SingletonDemo() {}
 
    public static SingletonDemo getInstance() 
    {
      if instance == null)
      {
          instance = new SingletonDemo();
      }
      return instance;
    }
}
In the above example, we have the method getInstance() which is providing the one and only one instance of the class. First it is checking if the object is instantiated or not(by checking if it is null or not). If it is not done yet then it creates a new instance. The instance is made static because only one class level instance variable will be there. 

     3. Make it Thread safe- This can be  achieved  either by:

                    1. Making getInstance() method synchronized 

public static synchronized SingletonDemo getInstance() {
        // code goes here
    }
                       2. Using Synchronized block

    public static SingletonDemo getInstance() {
      if (instance == null) {
       synchronized (SingletonDemo .class) {
        instance = new SingletonDemo ();
       }
      }
      return instance;
     }

    this method has one drawback. Suppose there are two threads T1 and T2. Both comes to create instance and execute “instance==null”, now both threads have identified instance variable to null thus assume they must create an instance. They sequentially goes to synchronized block and create the instances. At the end, we have two instances in our application.
    To  solve this double-checked locking can be used.

    public static SingletonDemo getInstance() {
      if (instance == null) {
       synchronized (SingletonDemo .class) {
    
         // Double check
     if (instance == null) {
           instance = new SingletonDemo ();
     }
       }
    }

    Let's have a look at few commonly used techniques to Create Singleton Class

    Eager initialization

    In his approach instance of a class is created much before it is actually required.lets see its code


    public class EaggerInitialzeSingletonDemo {
       private static EaggerInitialzeSingletonDemo instance 
                                      = new EaggerInitialzeSingletonDemo();
     
       private EaggerInitialzeSingletonDemo() {}
     
       public static synchronized EaggerInitialzeSingletonDemo getInstance() {
             return instance;
        }
    }

    Lazy initialization
    In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. This is typically accomplished by maintaining a flag indicating whether the process has taken place.Lets see it in code


    public class SingletonDemo{
     
        private static SingletonDemo instance;
     
        /** A private Constructor prevents any other class from instantiating. */
        private SingletonDemo() {}
     
        public static synchronized SingletonDemo getInstance() {
          if instance == null){
              instance = new SingletonDemo();
          }
          return instance;
        }
    }
    Static block initialization
    We know static blocks are executed during the loading of class and even before the constructor is called. We can use this feature

    public class StaticBlockSingleton {
     private static final StaticBlockSingleton INSTANCE;
    
     static {
      try {
       INSTANCE = new StaticBlockSingleton();
      } catch (Exception e) {
       throw new RuntimeException("Error", e);
      }
     }
    
     public static StaticBlockSingleton getInstance() {
      return INSTANCE;
     }
    
     private StaticBlockSingleton() {
            }
    }
    Above code has one drawback. Suppose there are 5 static fields in class and application code needs to access only 2 or 3, for which instance creation is not required at all. So, if we use this static initialization. we will have one instance created though we require it or not.

    Bill pugh solution

    Bill pugh suggest to use static inner class.
    public class BillPughSingleton {
       private BillPughSingleton() {
       }
    
       private static class LazyHolder {
           private static final BillPughSingleton INSTANCE = new BillPughSingleton();
       }
    
       public static BillPughSingleton getInstance() {
           return LazyHolder.INSTANCE;
       }
    }
    Using Enum
    public enum EnumSingleton {
     INSTANCE;
     public void someMethod(String param) {
      // some class member
     }
    }
    We can still create instances of the class by cloning the class. So we have to override the clone() method of the Object class so that if any attempt is made to clone the class it will throw a CloneNotSupportedException.
    public class SingletonDemo{
     
        private static volatile SingletonDemo instance;
     
        /** A private Constructor prevents any other class from instantiating. */
        private SingletonDemo() {}
     
        public static synchronized SingletonDemo getInstance() {
          if (instance == null) {
               synchronized (SingletonDemo .class) {
    
         // Double check
             if (instance == null) {
               instance = new SingletonDemo ();
           }
          return instance;
        }
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    }

    Still  we can create instances of the class by Serialization and de-serialization. So we need to override the readResolve() method also:
    The complete code is:

    public class SingletonDemo{
          private static volatile SingletonDemo instance;
     
    /** A private Constructor prevents any other class from instantiating. */
        private SingletonDemo() {}
     
        public static synchronized SingletonDemo getInstance() {
          if instance == null){
              instance = new SingletonDemo();
          }
          return instance;
        }
        protected Object readResolve() {
           return instance;
        }
       public Object clone() throws CloneNotSupportedException{
            throw new CloneNotSupportedException();
       }
    
    }
    FAQ's
    1. Why to use volatile with instance variable?
                  We should use “volatile” keyword with instance variable if we are using double checked locking otherwise we might see out of order write error scenario, where reference of instance is returned before actually the object is constructed i.e. JVM has only allocated the memory and constructor code is still not executed. In this case, our other thread, which refer to uninitialized object may throw null pointer exception and can even crash the whole application.
    For example: Thread A may assign a memory space for instance before it is finished constructing instance. Thread B will see that assignment and try to use it. This results in Thread B failing because it is using a partially constructed version of instance

    2.How Serialization and de- serialization can brake the code if readReolve() is not used?
                De-serialization always creates a new instance. Lets understand using an example:

    Our Singleton class without readResolve method


    public class SingletonDemo{
           private static volatile SingletonDemo instance;
           private int digit = 1;
    /** A private Constructor prevents any other class from instantiating. */ private SingletonDemo() {} public static synchronized SingletonDemo getInstance() { if instance == null){ instance = new SingletonDemo(); } return instance; }  
        public int getDigit() {
     return i;
        }
        public void setDigit(int i) {
     this.digit = i;
        }
    public Object clone() throws CloneNotSupportedException{ throw new CloneNotSupportedException(); }
    }
    Now we serialize this class and de-serialize it after making some changes

    public class SerializationTest {
         static SingletonDemo instanceOne = SingletonDemo.getInstance();
    
         public static void main(String[] args) {
     try {
        // Serialize to a file
        ObjectOutput out = new ObjectOutputStream(
                                       new FileOutputStream("demo.ser"));
        out.writeObject(instanceOne);
        out.close();
               instanceOne.setI(2);
        // Serialize to a file
        ObjectInput in = new ObjectInputStream(new FileInputStream(
         "demo.ser"));
        DemoSingleton instanceTwo = (SingletonDemo)in.readObject();
        in.close();
    
               System.out.println(instanceOne.getI());
        System.out.println(instanceTwo.getI());
    
           } catch (IOException e) {
         e.printStackTrace();
     } catch (ClassNotFoundException e) {
         e.printStackTrace();
     }
        }
    }
    
    Output:
    ===========================================================================
    2
    1
    We can See that two objects got created, thus defeating our purpose of making class singleton
    readResolve is used for replacing the object read from the stream. So this is enforcing singletons; when an object is read, replace it with the singleton instance. This ensures that nobody can create another instance by serializing and deserializing the singleton.

    3. Why we need to override the clone() Method?
               By default, the clone() method is marked as protected, but if our SingletonObject extends another class that does support cloning, it is possible to violate the design principles of the singleton. Examine the following code snippet, which clones a singleton object.

    Our Singleton class without clone method

    public class SingletonDemo{
    
          private static volatile SingletonDemo instance;
     /** A private Constructor prevents any other class from instantiating. */
    private SingletonDemo() {} public static synchronized SingletonDemo getInstance() { if instance == null){ instance = new SingletonDemo(); } return instance; }
        protected Object readResolve() {
    
           return instance;
        }
    }

    public class MyClone
    {
     public static void main(String args[])
       throws Exception
     {
       // Get a singleton
       SingletonDemo obj = SingletonDemo.getInstance0();
    
       // Let's clone the object
       SingletonDemo clone = (SingletonDemo) obj.clone();
     }
    }
    
    We can See that clone objects got created, thus defeating our purpose of making class singleton

    No comments :

    Post a Comment