Add

Singleton Pattern

Singleton pattern is for the cases when there is a need of only one instance and you want global access to it. For example, for Logging functionality at application level there would be need of only one instance. There can be other cases as well like Registry, Database Handler and many other options. In singleton pattern, the responsibility of instance creation of Singleton, is the responsibility of itself. In Singleton, private constructor is used so that no other class can create instance of it. There are three cases of Singleton pattern:

1) Singleton with Lazy Initialization


In lazy initialization, the Instance is created when it is needed. At first static instance variable is null. Now when getInstance() is used first time then it would be created. Next time whenever getInstance() would be used then already created instance would be returned.
    public class Logger
    {
        private static Logger _instance;
        /*
        * - Contructor should be private so that other classes will not 
        *   be able to create instance of it.
        * - Singleton is responsible itself for creation of its instance
        */
        private Logger()
        { 
        
        }
        public static Logger getInstance()
        {
            // Lazy initialization - instance would be created when needed
            if (_instance == null)
            {
                _instance = new Logger();
            }

            return _instance;
        }
    }
   


2) Singleton with Eager Approach


In this case the instance is created at the time of class creation. So each thread whenever would access the getInstance(), there would never be a case that static instance variable be null.
    // Due to "sealed", no derivation could be done. 
    // This class cannot be inherited.
    public sealed class LoggerEagerApproach
    {
	    // Instance is created at the time of class creation.  
        private static LoggerEagerApproach _instance = new LoggerEagerApproach();
        /*
        * - Contructor should be private so that other classes will not 
        *   be able to create instance of it.
        * - Singleton is responsible itself for creation of its instance
        */
        private LoggerEagerApproach()
        { 
        
        }
        public static LoggerEagerApproach getInstance()
        {
            // Eager initialization - instance is already created at the time
            // of creation of class.
            return _instance;
        }
    }


3) Thread-safe Singleton with Lazy Initialization


Simple Singleton class is not thread-safe. What if concurrency problem occurs? By concurrency problem, I am talking about the case when more than one threads are trying to access the getInstance() method and the instance is not yet created. To avoid this conflict, I have placed a lock that if instance is not assigned to static instance of the class then the first thread would be able to create the instance. All other threads accessing at the same time would get locked and would start waiting for the completion of the method getInstance() by first thread.
 
    // Due to "sealed", no derivation could be done. 
    // This class cannot be inherited.
    public sealed class LoggerWithMultiThreadedHandling
    { 
        private static volatile LoggerWithMultiThreadedHandling _instance;
        private static object objForSyncLock = new object();
        /*
        * - Contructor should be private so that other classes will not 
        *   be able to create instance of it.
        * - Singleton is responsible itself for creation of its instance
        */
        private LoggerWithMultiThreadedHandling()
        { 
        
        }
        public static LoggerWithMultiThreadedHandling getInstance()
        {
            // Double checking + Lazy Initialization 
            //                 + Concurrency problem handling
            if (_instance == null)
            {
                lock (objForSyncLock)
                {
                    if (_instance == null)
                    {
                        _instance = new LoggerWithMultiThreadedHandling();
                    }
                }
            }

            return _instance;
        }

    }