Sunday 13 March 2016

Singleton Design Pattern in Java

Singleton pattern ensures that only one instance of the class exists at a time in the whole JVM.

Use of Singleton Class:

Logger classes: Without creating a new object each time a logging operation is performed, we use a singleton of Logger classes


Servlets: Servlets are also based on singleton pattern, which however can be easily broken by defining servlet entry by another name in web.xml. Generally servlets are singletons. They are initialized at the beginning and later on only their service methods get called (i.e. doGet, doPost)

Configuration Classes: For example DB configuration class, generally is a singleton.

Let's move on to create our first singleton class Employee.


1. Make constructor of Employee class private so that no other class can create its object.
2. Create an instance variable of Employee type which refer the singleton Employee object
3.  Create a public static method that returns instance of Employee class.

Eager Loading way: Create Employee Singleton class using Eager loading i.e. object of Employee class is created when the class is loaded in JVM. 


package com.bpjoshi.singleton;   
  public class Employee {  
   //Make an Instance of Singleton class  
   private static final Employee instance = new Employee();   
   //make its constructor private  
   private Employee(){}   
   //Make a getInstance() method to retrieve the singleton  
   public static Employee getInstance(){   
      return instance;   
    }   
  }   

Singleton is used mostly with File Systems, Database Connections, Management Tools. They are using lots of important resources. Hence we should create its object only when it's needed.

Lazy Loading way: In this approach, singleton object is created when it's first time requested.


 package com.bpjoshi.singleton;  
 public class Employee {
   //Declare Instance of Singleton class
   private static final Employee instance;  
   //make its constructor private
   private Employee(){} 
   //Make a getInstance() method to retrieve the singleton
   public static Employee getInstance(){
     if(instance==null){
        instance= new Employee();
     }
     return instance;  
   }  
 } 


The above implementation works fine in a single threaded environment, however it will be easily destroyed in a multi threaded environment. If two or more threads access this resource simultaneously, they might get different object.

Thread Safe Singleton: You can easily make this singleton thread safe by making getInstance() Method synchronized.


 package com.bpjoshi.singleton;  
 public class Employee {
   //Declare Instance of Singleton class
   private static final Employee instance;  
   //make its constructor private
   private Employee(){} 
   //Make a getInstance() method to retrieve the singleton
   public static synchronized Employee getInstance(){
     if(instance==null){
        instance= new Employee();
     }
     return instance;  
   }  
 } 

Although the above implementation provides thread safety, yet it makes the program slower due to it being synchronized.

Bill Pugh Singleton: To overcome this issue of synchronization, Bill Pugh came up with his implementation using static inner helper class. Static inner class is not loaded into memory until its getInstance() method is not called.


 package com.bpjoshi.singleton;  
 public class Employee {
 //private constructor of employee
 private Employee(){}
 //private static inner helper class
 private static class EmployeeHelper{
    private static final Employee instance
      =new Employee();
 }
 //public method to get singleton object
 public static Employee getInstance(){
    return EmployeeHelper.instance;
   }
 } 

Bill Pugh Singleton is the best approach so far, however it can be easily destroyed with use of java reflection.

Breaking Bill Pugh Singleton with java Reflection:



package com.bpjoshi.singleton;
import java.lang.reflect.*;

public class EmployeeReflection {

    public static void main(String[] args) {
        Employee instance1 = Employee.getInstance();
        Employee instance2 = null;
        try {
            Constructor[] cstr 
             = Employee.class.getDeclaredConstructors();
            for (Constructor constructor : cstr) {
               //Setting constructor accessible
                constructor.setAccessible(true);
                instance2 
                   = (Employee) constructor.newInstance();
                break;
            }
        } catch (Exception e) {
             System.out.println(e);
        }
        System.out.println(instance1);
        System.out.println(instance2);
    }
}


Enum Singleton: We can use Enum to create singleton in java to come over the reflection. However the obvious drawback is we cannot have lazy loading in Enum.

public enum Employee{
    INSTANCE;
}

It's instance can be gotten by referring Employee.INSTANCE

Breaking Enum Singleton with Serialization:  If the Singleton class implements java.io.Serializable and a singleton object is serialized and then deserialized more than once, there will be many instances of Singleton.

In order to avoid serialization issue, implement readResolve() method in your Singleton class as below:

public class Employee implements Serializable {
   //some code here
  //call this method immediately after De-serialization
  //it returns an instance of singleton
  protected Object readResolve() {
   return getInstance();
   }
 }


That's it for this tutorial. If any queries or suggestions, please feel free to write in comments.

Happy Coding!

2 comments:

  1. Awesome blogs.
    It's very helpful for us!
    Thank you sir!

    I have a query sir! Please help me.
    ----> I have two jsp files home.jsp and login.jsp and a css file home.css but when i include home.jsp into login.jsp and run my file i found run properly but there are css is not working.

    ReplyDelete
    Replies
    1. Hi Sumit! Thanks!

      Make sure in your home.jsp page head section, the css file is included properly.

      If you want to use the same css in the login.jsp, the included file, then you will have to put the location of the css file in head section of login.JSP

      Delete

Please write your views