Saturday, 21 June 2014

Singleton Design Pattern in java with example

       I have attended some interviews recently. Some interviewer asked "do you know any design pattern"? I answered Singleton Design Pattern because even java beginners should know this pattern.
       Here we will learn about Singleton design pattern principles, different ways to implement Singleton and some of the best practices for it’s usage.

     Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine. The singleton class must provide a global access point to get the instance of the class. 

          Singleton pattern is used for logging, drivers objects, caching and thread pool. Singleton design pattern is also used in other design patterns like Abstract Factory, Builder, Prototype, Facade etc.

   To implement the Singleton Design Pattern,you do the following the things,
  1) private constructor - no other class can instantiate a new object.
  2) private reference - no external modification.
  3) public static method is the only place that can get an object.

 Next,we will learn the different approaches of Singleton pattern implementation and design.

Eager initialization

           In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a singleton class but it has a drawback that instance is created even though client application might not be using it.

Here is the implementation of static initialization singleton class.
   
            public class EagerInitializer{
                     private static final EagerInitializer instance = new EagerInitializer();
                             //private constructor to avoid client applications to use constructor.
                     private  EagerInitializer(){
                     }
                     public static EagerInitializer getInstance(){
                                 return instance;
                    }
           }

           If your singleton class is not using a lot of resources, this is the approach to use. But in most of the scenarios, Singleton classes are created for resources such as File System, Database connections etc and we should avoid the instantiation until unless client calls the getInstance method. Also this method doesn’t provide any options for exception handling.

Static block initialization

           Static block initialization implementation is similar to eager initialization, except that instance of class is created in the static block that provides option for exception handling

.              public class StaticInitializer{
                        private static StaticInitializer instance ;
                             //private constructor to avoid client applications to use constructor.
                        private  StaticInitializer(){
                        }
                        static {
                                try{
                                       instance=new StaticInitializer();
                                }
                                catch(Exception e){
                                        throw new RuntimeException("Exception in static block");
                                }
                        }
                        public static StaticInitializer getInstance(){
                                return instance;
                       }
             }

         Both eager initialization and static block initialization creates the instance even before it’s being used and that is not the best practice to use. So in further sections, we will learn how to create Singleton class that supports lazy initialization.

Lazy Initialization

           Lazy initialization method to implement Singleton pattern creates the instance in the global access method. Here is the sample code for creating Singleton class with this approach.

              public class LazyInitializer{
                      private static LazyInitializer instance;
                            //private constructor to avoid client applications to use constructor.
                      private  LazyInitializer(){
                      }
                      public static LazyInitializer getInstance(){
                              if(instance == null){
                                      instance = new LazyInitializer();
                              }
                              return instance;
                     }
           }


       The above implementation works fine incase of single threaded environment but when it comes to multithreaded systems, it can cause issues if multiple threads are inside the if loop at the same time. It will destroy the singleton pattern and both threads will get the different instances of singleton class. In next section, we will see different ways to create a thread-safe singleton class.

Thread Safe Singleton

       The easier way to create a thread-safe singleton class is to make the global access method synchronized, so that only one thread can execute this method at a time. General implementation of this approach is like the below class.

           public class ThreadSafe{
                    private static ThreadSafe instance ;
                        //private constructor to avoid client applications to use constructor.
                    private  ThreadSafe(){
                    }
                    public static synchronized ThreadSafe getInstance(){
                            if(instance == null){
                                     instance = new ThreadSafe();
                            }
                            return instance;
                   }
         }

        Above implementation works fine and provides thread-safety but it reduces the performance because of cost associated with the synchronized method, although we need it only for the first few threads who might create the separate instances (Read: Java Synchronization). To avoid this extra overhead every time, double checked locking principle is used. In this approach, the synchronized block is used inside the if condition with an additional check to ensure that only one instance of singleton class is created.

           Below code snippet provides the double checked locking implementation

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


                      Real time Examples for Singleton Design Pattern:---

JDBC Example using Singleton Design pattern:--

         We write a class (ConnectionFactory) which implements singleton pattern defining database connection configuration statements and methods to make connection to the database. Reason for making this class as singleton is, we can create one object of this class and can create many Connection objects (one factory, many objects).
package com.adnjavainterview;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionFactory {
           //static reference to itself
         private static ConnectionFactory instance = new ConnectionFactory();
         public static final String URL = "jdbc:mysql://localhost/jdbcdb";
         public static final String USER = "YOUR_DATABASE_USERNAME";
         public static final String PASSWORD = " YOUR_DATABASE_PASSWORD";
         public static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
              //private constructor
         private ConnectionFactory() {
                 try {
                        Class.forName(DRIVER_CLASS);
                  }
                  catch (ClassNotFoundException e) {
                        e.printStackTrace();
                  }
         }
    
         private Connection createConnection() {
                   Connection connection = null;
                   try {
                          connection = DriverManager.getConnection(URL, USER, PASSWORD);
                   }
                   catch (SQLException e) {
                           System.out.println("ERROR: Unable to Connect to Database.");
                   }
                   return connection;
         } 
    
         public static Connection getConnection() {
                 return instance.createConnection();
         }
 }
Transfer Object (TO) design pattern:

Transfer Object pattern encapsulates business data. To implement this pattern, we write a class with properties defining the table attributes. For example, to implement Employee TO class, we write the following code;

package com.adnjavainterview;

import java.util.Date;

public class Employee {
         private int empId;
         private String empName;
         private Date dob;
         private double salary;
         private int deptId;
          //getters and setters omitted for brevity
}
Data Access Object design pattern:

  DAO classes implements Data Access Object (DAO) pattern which encapsulates access to the data source.
       This class defines methods for each query, where we first create connection object using ConnectionFactory (by calling ConnectionFactory.getConnection()). Using this connection object we create statement and execute queries.
   
package com.adnjavainterview;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.adnjavainterview.ConnectionFactory;
import com.adnjavainterview.DbUtil;
import com.adnjavainterview.Employee;

public class EmployeeDAO {
        private Connection connection;
        private Statement statement;

        public EmployeeDAO() { }
    
        public Employee getEmployee(int employeeId) throws SQLException {
                 String query = "SELECT * FROM employee WHERE emp_id=" + employeeId;
                 ResultSet rs = null;
                 Employee employee = null;
                 try {
                       connection = ConnectionFactory.getConnection();
                       statement = connection.createStatement();
                       rs = statement.executeQuery(query);
                       . . . .
                       . . . .
                 } finally {
                         DbUtil.close(rs);
                         DbUtil.close(statement);
                         DbUtil.close(connection);
                  }
                  return employee;
       }
Closing database connection:
   Safe method to close database ResultSet, Statement and Connection is to write a finally block and release all the resources. We check for non-null reference before calling the close() instance method to avoid NullPointerException.
   
     finally {
            if (connection != null) {
                  try {
                        connection.close();
                  } catch (SQLException e) {
                        /* Ignore */
                  }
            }
            if (statement != null) {
                    . . .
            }
            if (resultSet != null) {
                   . . .
            }
      }

Instead of repeating these statements in all methods, we write a helper class (DbUtil.java) with methods to close these resources.
   
package com.adnjavainterview;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DbUtil {

         public static void close(Connection connection) {
                 if (connection != null) {
                       try {
                             connection.close();
                       } catch (SQLException e) {
                          /*log or print or ignore*/
                      }
                }
         }

        public static void close(Statement statement) {
                 if (statement != null) {
                       try {
                              statement.close();
                       } catch (SQLException e) {
                           /*log or print or ignore*/
                      }
               }
       }

        public static void close(ResultSet resultSet) {
                if (resultSet != null) {
                       try {
                              resultSet.close();
                       } catch (SQLException e) {
                             /*log or print or ignore*/
                       }
               }
        }
 }

These methods can be called from finally block.
   
          try {
                   connection = ConnectionFactory.getConnection();
                   statement = connection.createStatement();
                   rs = statement.executeQuery(query);
          } finally {
                   DbUtil.close(rs);
                   DbUtil.close(statement);
                  DbUtil.close(connection);
          }


Related Post:--

5 comments:

  1. Hello Sir,

    Thanks for such wonderful articles.

    It helped me a lot.

    I have one doubt over here.

    public class LazyInitializer{
    private static final LazyInitializer instance = null;
    //private constructor to avoid client applications to use constructor.
    private LazyInitializer(){
    }
    public static LazyInitializer getInstance(){
    if(instance == null){
    instance = new LazyInitializer();
    }
    return instance;
    }
    }

    In above example
    instance is declared as static final.

    And we can assign value to static final variable either at the line of declaration or in the static block.

    But here you are assigning value to static variable in getInstance() method.

    As per my knowledge it will give compile time error.

    Can you please clear my doubt?

    Thanks in Advance.

    Regards,
    Sagar

    ReplyDelete
  2. Nice Tutorial Anil, with real world example. it easy to understand for newbie.

    ReplyDelete
  3. How to restrict the object creation in java using singleton please refer this click here

    ReplyDelete