Singleton Design pattern


What is the design pattern?

  • In simple words, design patterns are best practices in the software development field.
  • These design patterns 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 the software development life cycle.
  • If you use the 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.
  • The instance is created even the 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.
  • The special thing is, we use the 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 a 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 double checking in thread section. This method uses 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;
    }
}

What is the double-checking on the Singleton design pattern?

  • Just think, you are using the code like below.
            synchronized (ThreadSafe.class){
                if(instance ==null){
                    instance = new ThreadSafe();
                }
            }
  • Here only one thread can acquire the lock of the object.
  • If many threads want to get the instance, all threads need to wait until one thread releases the lock of the object.
  • Since the synchronized block is using heavy CUP usage, it will consume more memory.
  • To resolve this, we can double-check the instance as follows.
            if(instance ==null){
                synchronized (ThreadSafe.class){
                    if(instance ==null){
                        instance = new ThreadSafe();
                    }
                }
            }
  • Now other threads will not reach the synchronized block. This will save CPU memory. 

What is the use of Volatile?

  • The volatile keyword can be used with variables.
  • Volatile variables will not be cached in the cache memory.
  • It will be saved only in the main memory. 
  • If one thread changed the value, all other threads can also see the changed value. 

The enum initialization

This is the most 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?

The 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 the 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;
   }
 
}




Singleton Design pattern Singleton Design pattern Reviewed by Ravi Yasas on 9:36 AM Rating: 5

No comments:

Powered by Blogger.