Singleton Design Pettarn - Details Explaination

What is singleton design pattern ?

Singleton design pattern allows programmer to create only one instance for a class for whole life cycle of process. In this case if developer tries to get new instance of class, he/she will get the same instance of the class which was created once.

Way of Implementation 
To implement singleton design pattern we must have to make all the constructor of the class private, so that developers can not create new instance of the class directly (Developer will not have control to create object of class).
There must be a static  method in class which will be called by developer to obtain the singleton object.

One method to implement the singleton design pattern is written below in code section.
    public class SingletonEx1
    {
        static SingletonEx1 SE1 = null;
        private SingletonEx1()
        {
        }
        public static SingletonEx1 getInstance()
        {
            if (SE1 == null)
                SE1 = new SingletonEx1();
            return SE1;
        }
        /*
         * other member functions
         */
    }
    public class CreateSingletonObj
    {
        SingletonEx1 se;
        public void createObject()
        {
            ///geting singleton instance
            se = SingletonEx1.getInstance();
        }
    }
    

Now if we see the above code, it looks like a proper code, but the above code is not feasible for multi-threaded environment, with thread switching.

Now suppose there are two threads trying to get 1st instance of the class simultaneously at the same time. Since the object is being accessed first time,so it is null and has to be instantiated. Now as thread-1 checks for (SE1==null), processor decides to send thread-1 to sleep mode. Since thread-1 has not instantiated the object SE1. Now its the turn of thread-2. It will now check for (SE1==null) since SE1 is still null so that it will instantiate the SE1 object and will return. Now processor resumes thread-1 since it has checked for SE1==null and found true, so that it will again instantiated SE1. So that 2 instance has been created. In this manner there will be race condition in this method.

To overcome this race condition, there are many other methods.
Method 1. Using Lock Variable:

    public class Global
    {
        public static object lockObj = (object)1;
    }
    public class SingletonEx1
    {
        static SingletonEx1 SE1 = null;
        private SingletonEx1()
        {
        }
        public static SingletonEx1 getInstance()
        {
            lock (Global.lockObj)
            {
                if (SE1 == null)
                    SE1 = new SingletonEx1();
                return SE1;
            }
        }
        /*
         * other member functions
         */
    }
    public class CreateSingletonObj
    {
        SingletonEx1 se;
        public void createObject()
        {
            ///geting singleton instance
            se = SingletonEx1.getInstance();
        }
    }
    

Method 2: Pre-Initialisation

    public class SingletonEx1
    {
        static SingletonEx1 SE1 = new SingletonEx1();
        private SingletonEx1()
        {
        }
        public static SingletonEx1 getInstance()
        {
                return SE1;
        }
        /*
         * other member functions
         */
    }
    public class CreateSingletonObj
    {
        SingletonEx1 se;
        public void createObject()
        {
            ///geting singleton instance
            se = SingletonEx1.getInstance();
        }
    }
    

In above method it is actually waste of memory, since static variable of class will be assigned memory first, even before the object of class is instantiated.

Method 3: Using Static inner Class(Bill Pugh Solution):

    public class SingletonEx1
    {
        
        private SingletonEx1()
        {
        }
        private static class singletonContainer
        {
           public static SingletonEx1 SE1 = new SingletonEx1();
        }
        public static SingletonEx1 getInstance()
        {
            return singletonContainer.SE1;
        }
        /*
         * other member functions
         */
    }
    public class CreateSingletonObj
    {
        SingletonEx1 se;
        
        public void createObject()
        {
            ///geting singleton instance
            se = SingletonEx1.getInstance();
        }
    }
    

In this solution we use inner static class which contains static variable of the class which is to be singleton.
In above code inner static class "singletonContainer" will be loaded on first execution of the "getInstance" method so that object will not be initialised before first execution of method as it was in Pre-Initialisation method of implementation.

No comments:

Post a Comment