11 September, 2014

Singleton design pattern - A quick guide

Singleton design pattern is the most useful pattern in real time scenario.Singleton pattern will ensure that there is only one instance of a class is created in the JVM. This implementation restrict the user to create multiple access point or instance. This is a creational design pattern. It has many implementation over java language, but singleton is an anti-pattern or bad practice.



There is 2 basic way for implementing singleton behavior.

  • Eager/Early Loading
  • Lazy Loading

Eager/Early Loading


Eager/Early loading is basically load of objects before actually use. But, sometimes it’s not recommended, if the object creation is expensive.


A simple example of eager or early loading.



/**
 * Eager/Early Loading
 * @author javalang
 *
 */
public class SingleTon {

private static final SingleTon OBJSINGLETON=new SingleTon();

private SingleTon(){
      if(OBJSINGLETON!=null)
            throw new IllegalStateException("This is singleton, object already exist");
};

public static SingleTon getInstance(){
      return OBJSINGLETON;
}

}



Lazy Loading


Lazy loading means the object will be load when it’s required. When we need the object that time only we need to create object. It’s useful and recommended. But the use of singleton is depends on the context or requirement. It’s always recommended when the operation is really expensive.

A simple example of lazy loading.


package com.jdeveloperguide.lab;

/**
 * Lazy Loading
 * @author jdeveloperguide
 *
 */
public class SingleTon {

private static SingleTon OBJSINGLETON=null;

private SingleTon(){
      if(OBJSINGLETON!=null)
            throw newIllegalStateException("This is singleton, object already exist");
};

//Call this method & create object only when required
public static SingleTon getInstance(){
      if(OBJSINGLETON==null){
            OBJSINGLETON=new SingleTon();
      }
      return OBJSINGLETON;
}

}



But, in the above example the singleton object is not useful for multi-threaded 
environment. This above singleton objects are not thread safe. 
You can use ‘synchronized’ keyword to make the object creation thread safe.
 
A simple example with synchronized keyword.
 

package com.jdeveloperguide.lab;

/**
 * Lazy Loading
 * @author jdeveloperguide
 *
 */
public class SingleTon {

private static SingleTon OBJSINGLETON=null;

private SingleTon(){
      if(OBJSINGLETON!=null)
            throw newIllegalStateException("This is singleton, object already exist");
};

//Call this method & create object only when required
public static SingleTon getInstance(){
            synchronized (SingleTon.class) {
                  OBJSINGLETON=new SingleTon();
            }          
      return OBJSINGLETON;
}
} 




In the above example the synchronized block allow the object creation thread safe. But the member variable is not thread safe yet. The member variable OBJSINGLETON is not thread safe here. 


Here is one important question for interview. How to make a variable thread safe?


Ans : By using volatile keyword.



But, there is one another better approach which will help us to cross check the implementation. By implementing the “Double-checked locking” we can make the singleton object more secure. This ensure the expensive operation of creating object is the very first call. 

package com.jdeveloperguide.lab;

/**
 * Lazy Loading
 * @author jdeveloperguide
 *
 */
public class SingleTon {

private static volatile SingleTon OBJSINGLETON=null;

private SingleTon(){
      if(OBJSINGLETON!=null)
            throw newIllegalStateException("This is singleton, object already exist");
};

//Create object only when required
public static SingleTon getInstance(){
      //1st Check
      if(OBJSINGLETON==null){
            synchronized (SingleTon.class) {
                  //2nd Check
                  if(OBJSINGLETON==null)
                  OBJSINGLETON=new SingleTon();
            }          
      }
      return OBJSINGLETON;
}
}


Now the singleton object OBJSINGLETON is thread safe. But, there is one more issue with singleton when we go for serialization. Because, during deserialization process it creates new object and it violate the singleton strategy. So, we should make sure that there is no new objects are created during deserialization. To avoid this issue you can use readResolve() method in serializable.



A simple example using readResolve() method.

package com.jdeveloperguide.lab;

import java.io.Serializable;

/**
 * Lazy Loading
 * @author jdeveloperguide
 *
 */
public class SingleTon implements Serializable {

private static volatile SingleTon OBJSINGLETON=null;
public static final long serialVersionUID=0L;

private SingleTon(){
      if(OBJSINGLETON!=null)
            throw newIllegalStateException("This is singleton, object already exist");
};

//Create object only when required
public static SingleTon getInstance(){
      //2nd Check
      if(OBJSINGLETON==null){
            synchronized (SingleTon.class) {
                  //2nd Check
                  if(OBJSINGLETON==null)
                  OBJSINGLETON=new SingleTon();
            }          
      }
      return OBJSINGLETON;
}

//This ensure the protection on serialization
@SuppressWarnings("unused")
private SingleTon readResolve(){
      return OBJSINGLETON;
}
}


 All the above example with implementations are traditional , which are not recommended by java 5 and above. There is one more better way to implement singleton strategy by using Enum. A simple example below using Enum.


package com.jdeveloperguide.lab;

/**
 * Singleton behavior using Enum
 * @author jdeveloperguide
 *
 */
public enum SingleTonEnum {
SINGLETONINSTANCE;
public void javaProgrammingStuff(){
      //Here is your stuffs
}
}


Enum provides lazy loading approach. Enum gives guaranty for thread safety and safety during serialization.

 



               

Interview Questions :


Q – What is serialVersionUID ?

Ans :- This maintain version number in complied class. It’s useful during deserialization process. During deserialization it maintains the similar copy as similar as serialization process.


Q – What is readResolve() method ?

Ans :- This method ensure a unique object during deserialization. It’s useful when implementing serialization over singleton object. It avoid to create new object during deserialization.





1 comment:

  1. Very nice information on java. You can also check goformule.com for mulesoft tutorials

    ReplyDelete