Tuesday, 8 March 2022

Singleton Design pattern


- it belongs to creational design pattern
- it deals with object creation mechanisms
- it is used to ensure that only one instance of a class is instantiated
- that single instance created is responsible to coordinate actions across the application

- Guidelines for creating singleton class
1. Mark class sealed so that we will restrict it from being inherited. Also if someone creates nested class within singleton class then user can create any number of instances for nested class which breaks our main goal of single instance.
2. Create a private static instance of singleton class inside it.
3. Make a public property GetInstance, which will first check whether we already initialized class or not, using private variable. If class is already created return that or else initialize singleton class and return its instance.
4. Create a private constructor. Private constructor ensures that instance of class can only be created internally not externally.
5. Also inside public property GetInstance lock an object so that instance creation will be thread safe. No two threads will access property at same time.

## Lazy Initialization in Singleton
GetInstance Property is responsible for the Singleton Instance creation. Singleton object is not instantiated until and unless GetInstance is invoked. Hence, there is a delay in instance creation till the GetInstance is accessed. This Delay in Instance creation is called Lazy Initialization.

## How to use Multithreads in Singleton
The lazy initialization works perfectly well when we invoke the GetInstance in a Single threaded approach. However, there is a chance that we may end up creating multiple instances when multiple threads invoke the GetInstance at the same time.

## How to implement a Thread Safe singleton class
Locks are the best way to control thread race condition and they help us to overcome the present situation. Please refer to the Singleton.cs code for lock checks and double check locking.

```code c#
Singleton Class Implementation Example

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// First version of Singleton demo
/// </summary>
namespace SingletonDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Parallel.Invoke(
                () => PrintStudentdetails(),
                () => PrintEmployeeDetails()
                );
            Console.ReadLine();
        }

        private static void PrintEmployeeDetails()
        {
            /*
             * Assuming Singleton is created from employee class
             * we refer to the GetInstance property from the Singleton class
             */
            Singleton fromEmployee = Singleton.GetInstance;
            fromEmployee.PrintDetails("From Employee");
        }

        private static void PrintStudentdetails()
        {
            /*
             * Assuming Singleton is created from student class
             * we refer to the GetInstance property from the Singleton class
            */
            Singleton fromStudent = Singleton.GetInstance;
            fromStudent.PrintDetails("From Student");
        }
    }
}

Singleton.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// First Singleton version
/// </summary>
namespace SingletonDemo
{
    /*
     *  Sealed ensures the class being inherited and
     *  object instantiation is restricted in the derived class
     */
    public sealed class Singleton
    {
        private static int counter = 0;
        private static readonly object obj = new object();

        /*
         * Private property initilized with null
         * ensures that only one instance of the object is created
         * based on the null condition
         */
        private static Singleton instance = null;
       
        /*
         * public property is used to return only one instance of the class
         * leveraging on the private property
         */
        public static Singleton GetInstance
        {
            get
            {
                if (instance == null)
                {
                    lock (obj)
                    {
                        if (instance == null)
                            instance = new Singleton();
                    }
                }
                return instance;
            }
        }
        /*
         * Private constructor ensures that object is not
         * instantiated other than with in the class itself
         */
        private Singleton()
        {
            counter++;
            Console.WriteLine("Counter Value " + counter.ToString());
        }
        /*
         * Public method which can be invoked through the singleton instance
         */
        public void PrintDetails(string message)
        {
            Console.WriteLine(message);
        }
    }
}
```

No comments:

Post a Comment

Search This Blog

Creating your first "Alexa" Skill

Index What is Alexa What is Alexa Skill? Why is it required when Alexa already equipped with voice assistant? Dev...