Saturday 3 January 2015

Singleton design pattern

Singleton design pattern


Ensure a class only has one instance, and provide a global point of access to it.
The Singleton's purpose is to control object creation, limiting the number of objects to one only. 
Sometimes it's important to have only one instance for a class.


A class that implements the singleton design pattern must prevent multiple instantiations. Relevant techniques include:
1. Make constructor private
2. Provide a public static method to accessing/sharing the singleton object. 

Real time Application of Singeton class:
1. Logger Classes
2. Configuration Classes
3. Factories implemented as Singletons

First Solution:
Use a private constructor
Use static method to get Single object
  
class SingleTon
{
    private static final single;

    private SingleTon() {} 

    public static SingleTon SingleTon()
    {
       if(single==null)
       {
             single = new SingleTon();
       }
       return single;
   }
}

Cons: fail in multithreaded environment



Second Solution: Multi threaded version: use synchronized method

class SingleTon
{
    private static final single; 
    private SingleTon() {}
    public static SingleTon synchronized SingleTon()
    {
         if(single==null)
         {
              single = new SingleTon();
         }
         return single;
    }
}


Third solution: synchronized block with double checking

class SingleTon
{
    private static final  volatile single; 
    private SingleTon() {}
    public static SingleTon SingleTon()
    {
         if(single==null)
         {
               synchronized(single)
               {
                     if(single==null)
                     {
                            single = new SingleTon();
                     }
               }
          }
          return single;
    }
}

Fourth Solution: Solution for serialization:  use readResolve() 

class SingleTon implements Serializable
{
    private static final single; 
    private SingleTon() {}
    public static SingleTon syncronized SingleTon()
    {
         if(single==null)
         {
              single = new SingleTon();
         }
         return single;
    }

   private Object readResolve()
   {
         // Return the one true object and let the garbage collector take care of the new object
         return INSTANCE;
   }
}


Fifth solution: Avoid cloning: throw clone not supported exception

Add following method in Singleton class:

public Object clone() throws CloneNotSupportedException
{
      throw new CloneNotSupportedException("");
}



Solution six: Singleton class loaded by different class loaders

If you want to create true singleton, you should avoid using custom classloaders - all singletons should be loaded by common parent classloader.
If you want to make sure the same classloader loads your singletons, you must specify the 
classloader yourself

private static Class getClass(String classname) throws ClassNotFoundException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if(classLoader == null)
        classLoader = Singleton.class.getClassLoader();
    return (classLoader.loadClass(classname));

}


Please note:

Cases where singleton may break:

1. Multiple Singletons in Two or More Virtual Machines
When copies of the Singleton class run in multiple VMs, an instance is created for each machine.

2. Multiple Singletons Simultaneously Loaded by Different Class Loaders
When two class loaders load a class, you actually have two copies of the class, and each one can have its own Singleton instance.

3. Singleton Classes Destroyed by Garbage Collection, then Reloaded
When a Singleton class is garbage-collected and then reloaded, a new Singleton instance is created. Any class can be garbage-collected when no other object holds reference to the class or its instances. If no object holds a reference to the Singleton object, then the Singleton class may disappear, later to be reloaded when the Singleton is again needed. In that case, a new Singleton object will be created. Any static or instance fields saved for the object will be lost and reinitialized.

ReadResolve method explanation: 

readResolve is used for replacing the object read from the stream. The only use I've ever seen for this is enforcing singletons; when an object is read, replace it with the singleton instance. This ensures that nobody can create another instance by serializing and deserializing the singleton.

ReadResolve is called after readObject has returned (conversely writeReplace is called before writeObject and probably on a different object). The object the method returns replaces this object returned to the user of ObjectInputStream.readObject and any further back references to the object in the stream. It is mostly used for serial proxies

No comments:

Post a Comment