Saturday, August 20, 2016

Singleton pattern - step by step guide

                                              
Goal:  to have single object as long as app exists

How to achieve that:

     Step 1:  have a private constructor of the class
              This helps, you can’t create object of the class from outside

 Class singleton{   
     Private singleton(){   
     }   
   }  

Ok, then How to create an object

Step 2:  Have a static public function
        Responsibility of this function is to create an object
     Why public  scope :  So that, this function can be called from outside
     Why static  : this function can be called without creating object of it .

 Class singleton{  
      Private static singleton singletonObj;  
       Private singleton(){  
       }  
       Public static singleton getInstance(){  
          If(null == singletonObj )  
            singletonObj = new singleton();  
        return singletonObj;  
       }   
   }  

We have now created singletonObj as single instance.
    Is my job over ?    this implementation is good as long as you are working with single threaded application.  But, the modern applications are using multithreaded.


Step 3:  Use synchronized block
     
 Public static singleton getInstance(){   
     Synchronized(singleton.class) {   
      If(null == singletonObj )   
       singletonObj = new singleton();   
      }   
     return singletonObj;   
     }   

Well, we have achieved it.  
  Now,  Assume singletonObj created, Thread t1 and t2 going to call this method to get the singletonObj.
   Thread t1 calling this method, as soon as it enters in to the function, lock is acquired because of the synchronized block. And t1 is not exiting this function.
    Now , t2 calling this method , as already lock is held by Thread t1, Thread t2 will wait to release the lock.
     This is performance issue .


Step 4 :  Add null check

Public static singleton getInstance(){   
      If(null == singletonObj ) {   
     Synchronized(singleton.class) {   
      If(null == singletonObj )   
       singletonObj = new singleton();   
      }   
     }   
     return singletonObj;   
     }   

If object is created, then it will call the return method directly.

Another optimization technique is, Using different lock

 Class singleton{  
      Private static singleton singletonObj;  
      Private Object lockObj = new Object();  
       Private singleton(){  
       }  
      Public static singleton getInstance(){  
          If(null == singletonObj ) {  
           Synchronized(lockObj) {  
              If(null == singletonObj )  
             singletonObj = new singleton();  
         }  
       }  
        return singletonObj;  
       }  
   }  

In case you have different function holding singleton class lock, then without any problem you can access this function.
   But still the previous implementation holds good, because synchronized function gets executed only once (ie till creation of the object ) whereas in new implementation we have created object, that will be alive till the app exists.     

No comments:

Post a Comment