Saturday, 21 June 2014

Singleton Design Pattern in Java with Examples

         In this post, we will learn the principles of the Singleton design pattern, explore different ways to implement it, and discuss some best practices for using it.

       The Singleton design pattern restricts the instantiation of a class, ensuring that only one instance of the class exists within the Java Virtual Machine (JVM). A Singleton class provides a global access point through which the single instance of the class can be accessed.

       The Singleton design pattern is commonly used for logging, database driver objects, caching, configuration management, and thread pools. It is also used by several other design patterns, such as Abstract Factory, Builder, Prototype, and Facade.

To implement the Singleton Design Pattern, the following principles should be followed:

  1. Private constructor – Prevents other classes from creating new instances of the class.

  2. Private static instance reference – Holds the single instance of the class and prevents external modification.

  3. Public static method – Provides a global access point to retrieve the Singleton instance.


Below are the different approaches for implementing the Singleton design pattern.

  • Eager initialization

            In eager initialization, the Singleton instance is created when the class is loaded into memory. This is the simplest way to implement the Singleton design pattern. However, it has one drawback: the instance is created even if the client application never uses it, which may result in unnecessary memory usage.
Below is the implementation of the Singleton class using eager initialization.     

  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 does not consume many resources, eager initialization is a suitable approach. However, in most real-world scenarios, Singleton classes are used to manage resource-intensive objects such as file systems, database connections, or configuration managers. In such cases, it is better to delay the creation of the instance until the client invokes the getInstance() method.

Another limitation of eager initialization is that it does not provide flexibility for handling exceptions that may occur during instance creation.

  • Static block initialization

            The static block initialization approach is similar to eager initialization, except that the Singleton instance is created inside a static initialization block. This approach provides the flexibility to handle exceptions that may occur during instance creation.

 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 create the Singleton instance before it is actually needed. In many cases, this is not considered a best practice because the instance is created even if it is never used. In the following sections, we'll explore how to implement a Singleton class that supports lazy initialization.

  • Lazy Initialization

            The lazy initialization approach creates the Singleton instance only when it is requested through the global access method (getInstance()). This ensures that the instance is created only when it is actually needed.

Below is a sample implementation of the Singleton design pattern using the lazy initialization 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 well in a single-threaded environment. However, in a multithreaded environment, it can cause issues if multiple threads enter the if block simultaneously. In such a scenario, multiple instances of the Singleton class may be created, violating the Singleton design pattern and causing different threads to obtain different instances.

In the next section, we'll explore different approaches for implementing a thread-safe Singleton class.

  • Thread Safe Singleton

       The simplest way to make a Singleton class thread-safe is to synchronize the global access method (getInstance()). This ensures that only one thread can execute the method at a time, preventing multiple instances from being created concurrently.

A typical implementation of this approach is shown below.


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

         The above implementation is thread-safe and works correctly. However, it can reduce performance because every call to the getInstance() method requires synchronization, even after the Singleton instance has already been created. In practice, synchronization is only needed when the instance is created for the first time.

To avoid this unnecessary synchronization overhead, the Double-Checked Locking pattern is used. In this approach, the instance is checked before entering the synchronized block and checked again inside the synchronized block. This ensures that synchronization occurs only during the initial creation of the Singleton instance while maintaining thread safety.

The following code snippet demonstrates the Double-Checked Locking implementation.


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


JDBC Example using Singleton Design pattern:--

          A common real-world example of the Singleton design pattern is a ConnectionFactory class. This class is implemented as a Singleton and contains the database connection configuration along with methods for creating database connections.

The reason for making the ConnectionFactory class a Singleton is that only one instance of the factory is required throughout the application. This single factory instance can then be used to create multiple database Connection objects whenever needed—one factory, many connections.


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();
         }
 }

Thank you for visiting blog..

Related Post:--

9 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
    Replies
    1. Thanks sagar...I corrected it.

      Delete
    2. Really nice article and well explained. But this is for single threaded applications. So what about multiple thread application. I found a really great explanation and solution there.

      Delete
  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
  4. "Great blog created by you. I read your blog, its best and useful information. You have done a great work. Super blogging and keep it up.php jobs in hyderabad.
    "

    ReplyDelete
  5. Great Blog Anil,its really helps lot .

    ReplyDelete
  6. Well explained . Great article on singleton pattern . There is also good singleton pattern example visit Singleton class example

    ReplyDelete