Friday, June 17, 2016

Singleton Design pattern


What is a design pattern ?

  • In simple words, design patterns are best practices in software developing field.
  • These design patters are invented by well experienced Object Oriented Software developers using their practice and experience.

Singleton design pattern

  • This design pattern can be used to control object creation of software development life cycle.
  • If you use Singleton design pattern, then you can have only one instance of that type.

How to create a Singleton object ?

  • Create private constructor (Then no one can instantiate this class, it means others can't create objects)
  • Create the only one private static instance
  • Create a public method to invoke this instance

Types of singleton implementations

There are several ways to implement a singleton class.
  1. Eager initialization
  2. Static block initialization
  3. Lazy initialization
  4. Thread safe initialization
  5. Enum initialization

Eager initialization

  • In this method, the instance is created at the time of class loading.
  • Instance is created even client is requesting or not.

public class Singleton{

    private static final Singleton instance = new Singleton();

    private Singleton() { }

    public static Singleton getInstance() {
       return instance;
    }
}


Static block initialization

  • This is very same as Eager initialization.
  • Special thing is, we use static block in getInstance() method to have exception handling.

public class Singleton{

    private static Singleton instance;

    private Singleton() { }

    static{
        try {
            instance = new Singleton(); 
        }catch (Exception e) {
            System.out.println("Error : " + e);
        }
    }
 
    public static Singleton getInstance(){
        return instance;
    }
}


Lazy initialization

  • This is a good one in single threaded environment.
  • But in multithreaded environment, we have to use thread safe initialization.

public class Singleton{

    private static Singleton instance;

    private Singleton() { }

    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}


Thread safe initialization

  • This is just very similar to Lazy initialization.
  • But here synchronize the method that can be used to get the instance in multi threaded environment.

public class Singleton{

    private static Singleton instance;

    private Singleton() { }

    public static synchronized Singleton getInstance(){
        if(instance == null){
             instance = new Singleton();
        }
        return instance;
    }
}

I think you can remember, I have mentioned something called doubled check in thread section. In this method, it is used a synchronized block. Here you can see how to implement this.

public class Singleton {

    private volatile static Singleton instance;

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


Enum initialization

This is very efficient way to implement a singleton. Because it is very easy to write. Here is the way to implement it.

public enum EnumSingleton{
      instance;
}

You can get the instance by calling EnumSingleton.instance

Which is the best one ?

Enum singleton implementation is the best way, because it is very easy to implement and use. But this is available since Java 5.

When to use Singleton design pattern ?

  • To manage shared resources(Database connections, file manager)
  • Logging
  • Catching

Singleton in JDK

There are many singleton classes that can be found in JDK. I listed three of them.
  • In java.lang.Runtime which provides getRuntime() method.
  • In java.awt.Toolkit which provides getDefaultToolkit() method.
  • In java.awt.Desktop which provides getDesktop() method.

Use of Singleton pattern when creating a database connection


package com.app.design.singleton;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Singleton {

   private static Singleton instance;
   private static Connection connection;
 
   private Singleton(){
  
      String driver = "com.mysql.jdbc.Driver";
      String url = "jdbc:mysql://localhost:3306/database";
      String username = "username";
      String password = "password";
  
      try{
          Class.forName(driver);
              try{
                  connection = DriverManager.getConnection(url, username, password);
              }catch(SQLException e){
                  e.getMessage();
              }
      }catch(ClassNotFoundException e){
          e.getMessage();
      }
   }
 
   public static Singleton getInstance(){
  
      if(instance == null){
          synchronized (Singleton.class){
             if(instance == null){
                 instance = new Singleton();
             }
          }
      }
      return instance;
   }
 
}