Singleton

Requirement

  • Single instance of a class for a particular JVM or across the JVM

Usage Scenario

  • Caching of Application, Resources, System, User and Global data
  • Lazy Loading

Example

  • java.lang.Runtime
  • Logger

How to create a Singleton Class : Three fundamental rule

  • Make constructor as private to restrict instantiation of the class from other classes/calling classes.
  • Private static variable of the same class that is the hold the instance of the class.
  • Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.

Scenario and Usage Details :-

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.

Here is the implementation of static initialization singleton class.

package com.easycasestudy.designpattern.singleton;
public class SimpleSingleton {
          private static final SimpleSingleton _instance = new SimpleSingleton();

          //private constructor to avoid client applications to use constructor

          private SimpleSingleton(){}
          public static SimpleSingleton getInstance(){

              return _instance;

          }
}

Or

package com.easycasestudy.designpattern.singleton;
public class StaticSingleton {
    private static StaticSingleton _instance;
    private StaticSingleton(){}

    //static block initialization for Singleton class
    static{
            _instance = new StaticSingleton();
    }
    public static StaticSingleton getInstance(){
        return _instance;
    }
}

Drawback :-

  • Thread Un Safe
  • Instance is created before its use.

When to use this approach :-

  • Singleton class is not using any resource
  • Application is not designed for multi-threaded environment
  • Once it is loaded resources are used for only retrieval not for modification.

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

package com.easycasestudy.designpattern.singleton;

public class LazySingleton {

private static LazySingleton _instance;

private LazySingleton(){}

//Object will initialize only when this class is being called

public static LazySingleton getInstance(){

if(_instance == null){

_instance = new LazySingleton();

}

return _instance;

}

}
Drawback :-
  • Thread Un Safe
  • Instance is created before its use.
When to use this approach :-
  • Singleton class is not using any resource
  • Application is not designed for multi-threaded environment
  • Once it is loaded resources are used for only retrieval not for modification

Thread Safe Singleton

package com.easycasestudy.designpattern.singleton;

public class ThreadSafeSingleton {

      //Classes's Instance reference volatile.

      private static volatile ThreadSafeSingleton instance;

      // Private Constructor

        private ThreadSafeSingleton()  {

        }

        public static ThreadSafeSingleton getInstance() {

          if (instance == null) {

            synchronized (ThreadSafeSingleton.class) {

              if (instance == null)

                instance = new ThreadSafeSingleton();

            }

          }

          return instance; 

        }

}

Singleton Using Inner Class

Prior to Java 5, java memory model had a lot of issues and above approaches used to fail in certain scenarios where too many threads try to get the instance of the Singleton class simultaneously. So Bill Pugh came up with a different approach to create the Singleton class using a inner static helper class. The Bill Pugh Singleton implementation goes like this

package com.easycasestudy.designpattern.singleton;
public class SingletonInnerClass {
    private SingletonInnerClass(){}
    private static class InnerClass{
        private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();
    }
    public static synchronized SingletonInnerClass getInstance(){
            return InnerClass.INSTANCE;
    }
}

 

ENUM Singleton Class

package com.easycasestudy.designpattern.singleton;

public enum EnumSingleton {
      _INSTANCE;
       public void method1()
       {
          System.out.println("Methos 1 is called");
       }
       public void method2()
       {
         System.out.println("METHOD 2 IS CALLED");

       }
}
Advantage
  1. Simple and more effective
  2. Thread Safe
  3. Serialization – De-Serialization Safe

Test Class – This example show Enum classes are Serialization – De-Serialization Safe.

package com.easycasestudy.designpattern.singleton;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

public class EnumSingletonTest {
      public static void main(String[] args) {
              EnumSingleton._INSTANCE.method1();
              EnumSingleton._INSTANCE.method2();
              ObjectOutput out;
            try {
              out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
              out.writeObject(EnumSingleton._INSTANCE);
              out.close();
              //deserailize from file to object
              ObjectInput in = new ObjectInputStream(new FileInputStream(
                      "filename.ser"));
              Object instanceTwo = (Object) in.readObject();
              in.close();
              System.out.println("instanceOne hashCode="+EnumSingleton._INSTANCE.hashCode());
              System.out.println("instanceTwo hashCode="+instanceTwo.hashCode());
            } catch (IOException e) {
                  e.printStackTrace();

            } catch (ClassNotFoundException e) {

                  e.printStackTrace();

            }

            }
}

OUTPUT

Methos 1 is called

METHOD 2 IS CALLED

instanceOne hashCode=118352462

instanceTwo hashCode=118352462

Serializable Singleton Class
package com.easycasestudy.designpattern.singleton;

import java.io.Serializable;

public class ThreadSafeSingleton implements Serializable{

private static final long serialVersionUID = -1462366506268589899L;

//Classes's Instance reference volatile.

private static volatile ThreadSafeSingleton instance;

// Private Constructor

private ThreadSafeSingleton()  {

}

public static ThreadSafeSingleton getInstance() {

if (instance == null) {

synchronized (ThreadSafeSingleton.class) {

if (instance == null)

instance = new ThreadSafeSingleton();

}

}

return instance;

}
//readResolve to prevent another instance of Singleton

private Object readResolve(){

return instance;

}

}
CLONE NOT SUPPORTED SINGLETON
package com.easycasestudy.designpattern.singleton;

import java.io.Serializable;

public class ThreadSafeSingleton implements Serializable, Cloneable{

private static final long serialVersionUID = -1462366506268589899L;

//Classes's Instance reference volatile.

private static volatile ThreadSafeSingleton instance;

// Private Constructor

private ThreadSafeSingleton()  {

}

public static ThreadSafeSingleton getInstance() {

if (instance == null) {

synchronized (ThreadSafeSingleton.class) {

if (instance == null)

instance = new ThreadSafeSingleton();

}

}

return instance;

}
//readResolve to prevent another instance of Singleton

private Object readResolve(){

return instance;

}
@Override
protected Object clone() throws CloneNotSupportedException {
/*
* Here forcibly throws the exception for preventing to be cloned
*/

throw new CloneNotSupportedException();

}
}

Discussion Point

1)       Singletons frequently are used to provide a global access point for some service.
True, they do this, but at what cost? They provide a well-known point of access to some service in your application so that you don’t have to pass around a reference to that service. How is that different from a global variable? (remember, globals are bad, right???) What ends up happening is that the dependencies in your design are hidden inside the code, and not visible by examining the interfaces of your classes and methods. You have to inspect the code to understand exactly what other objects your class uses. This is less clear than it could be. The urge to create something as a global to avoid passing it around is a smell in your design; it is not a feature of globals/singletons. If you examine your design more closely, you can almost always come up with a design that it is better and does not have to pass around tramp data to every object and method.

2)       Singletons allow you to limit creation of your objects.
This is true, but now you are mixing two different responsibilities into the same class, which is a violation of the Single Responsibility Principle. A class should not care whether or not it is a singleton. It should be concerned with its business responsibilities only. If you want to limit the ability to instantiate some class, create a factory or builder object that encapsulates creation, and in there, limit creation as you wish. Now the responsibilities of creation are partitioned away from the responsibilities of the business entity.

3)       Singletons promote tight coupling between classes
One of the underlying properties that makes code testable is that it is loosely coupled to its surroundings. This property allows you to substitute alternate implementations for collaborators during testing to achieve specific testing goals (think mock objects). Singletons tightly couple you to the exact type of the singleton object, removing the opportunity to use polymorphism to substitute an alternative. A better alternative, as discussed in the first point above, is to alter your design to allow you to pass references to objects to your classes and methods, which will reduce the coupling issues described above.

4)       Singletons carry state with them that last as long as the program lasts
Persistent state is the enemy of unit testing. One of the things that makes unit testing effective is that each test has to be independent of all the others. If this is not true, then the order in which the tests run affects the outcome of the tests. This can lead to cases where tests fail when they shouldn’t, and even worse, it can lead to tests that pass just because of the order in which they were run. This can hide bugs and is evil. Avoiding static variables is a good way to prevent state from being carried from test to test. Singletons, by their very nature, depend on an instance that is held in a static variable. This is an invitation for test-dependence. Avoid this by passing references to objects to your classes and methods.