Saturday, January 2, 2016

Singleton Design Pattern


It involves only one class which is responsible for instantiating itself, to make sure it creates not more than one instance; at the same time, it provides a global point of access to that instance. In this case, the same instance can be used from everywhere, being impossible to invoke directly the constructor each time.
·        Ensure that only one instance of a class is created.
·        Provide a global point of access to the object.

The implementation involves :
·        A static member in the "Singleton" class
·        A private constructor
·        A static public method that returns a reference to the static member.
Creational Design Pattern as it hides implementation of object
Standard Implementation
// Thread-safe implementation but with expensive Synchronize method...
package com.java.designpatterns;

public class SingletonDP {

          // Only 1 shared instance
          private static SingletonDP instance;

          // The constructor should not be accessible from the outside of the class.So that Constructor won't be visible to other classes...
          private SingletonDP() {
          }

          // To make it thread safe...To avoid two threads running the same method at once
          public static synchronized SingletonDP getInstance() {
                   if (instance == null)
                             instance = new SingletonDP();
                   return instance;
          }
}

class Client{
     public static void main(String[] args) {
           // can't instantiate the object
           SingletonDP singletonDp = new SingletonDP();
           SingletonDP singletonDP= SingletonDP.getInstance();
     }

}

Lazy Loading- Waiting for the first request to come from client side although the server is up.
The standard implementation shown in the above code is a thread safe implementation, but it's not the best thread-safe implementation because synchronization is very expensive when we are talking about the performance.

Lazy instantiation using double locking mechanism


If we see that the singleton object is already created we just have to return it without using any synchronized block. This optimization consists in checking in an unsynchronized block if the object is null and if not to check again and create it in a synchronized block. This is called double locking mechanism.
package com.java.designpatterns;

//Lazy instantiation using double locking mechanism...
public class SingletonLazy {

          //Single instance of class
          private static SingletonLazy instance;
         
          //Not visible to other classes...
          private SingletonLazy() {
                   System.out.println("Singleton(): Initializing Instance");
          }

          //Synchronized check only after checking whether instance exists or not...
          public static SingletonLazy getInstance() {
                   if (instance == null) {
                             synchronized (SingletonLazy.class) {
                                      if (instance == null) {
                                                System.out.println("getInstance(): First time getInstance was invoked!");
                                                instance = new SingletonLazy();
                                      }
                             }
                   }

                   return instance;
          }
          public static void main(String[] args) {
                   System.out.println(SingletonLazy.getInstance());
          }
}

In this case, the singleton instance is created when the getInstance() method is called for the first time. This is called lazy instantiation and it ensures that the singleton instance is created only when it is needed.

Early instantiation using implementation with static field


The singleton object is instantiated when the class is loaded and not when it is first used, due to the fact that the instance member is declared static. This is why in we don't need to synchronize any portion of the code in this case. The class is loaded once this guarantees the uniqueness of the object.

package com.java.designpatterns;

public class SingletonEarly {

          private static SingletonEarly instance = new SingletonEarly();

          private SingletonEarly() {
                   System.out.println("Singleton(): Initializing Instance");
          }

          public static SingletonEarly getInstance() {
                   return instance;
          }

}

Singleton and Object Cloning

Cloning is used to create a copy of the object at any instance original object by implementing java.lang.Cloneable interface and override clone() method from Object class.

To prevent cloning on singleton object, explicitly throw CloneNotSupportedException exception in clone() method.

Singleton and Serialization

Java Serialization allows converting the state of an object into the stream of bytes to store or transfer. Deserialization used to convert byte stream into. If a singleton class desterilized, it will end up creating duplicate objects.

To resolve this issue, we need to include readResolve() method in our class which will be invoked before the object is desterilized. We will return INSTANCE by call getInstance () method inside readResolve() which will ensure the single instance of Singleton class is exist application.

import java.io.Serializable;
class Singleton implements Cloneable, Serializable {
       private static final long serialVersionUID = 1L;
       private static Singleton instance;
       private int value;

       /* Private Constructor prevents any other class from instantiating */
       private Singleton() {
       }
       public static synchronized Singleton getInstance() {

              /* Lazy initialization, creating object on first use */
              if (instance == null) {
                     synchronized (Singleton.class) {
                           if (instance == null) {
                                  instance = new Singleton();
                           }
                     }
              }
              return instance;
       }

       /* Restrict another object creation in serialization. */
       protected Object readResolve() {
              return getInstance();
       }

       /* Restrict cloning of object */
       @Override
       public Object clone() throws CloneNotSupportedException {
              throw new CloneNotSupportedException();
       }

       public void display() {
              System.out.println("Hurray! I am display from Singleton!");
       }

       public int getValue() {
              return value;
       }

       public void setValue(int value) {
              this.value = value;
       }
}

Singleton real time example :
     
     1)     Runtime runtime=Runtime.getRuntime();  
     2)     Spring container
     3)     LogManager.getLogManager();

    Some more Real Time Applications :

1) Project Configuration: Class that reads your project configuration should be made Singleton by reads once and holds on application Cache and global access to all classes in application.

2) Application Log: Logger must be initialized once and used everywhere in application.

3) Analytics and Reporting: If you are using some kind of data analysis tool like Google Analytics, you will notice that they are designed to be singleton. It initializes once and being used everywhere for each user action.

No comments:

Post a Comment