Wednesday, April 22, 2020

Singleton design pattern

Singleton design pattern is all about ensuring that a class has only one instance in the application. It is a design pattern from Creational Pattern of Gang of Four (GOF) Design Patterns.
In this pattern, we have to restrict creating the instance if it is already created and use the existing one.
First of all, we have to make our class constructor as a private so that we can not create object from outside of the class using the new keyword.
We have many approaches to use singleton design pattern in C#. Here, we are going through a few of them.
Let’s start with the example for better understanding.
We are using console application for this example and we are going to take Employee class and will use a private constructor.
First approach 
  1. public class Employee  
  2. {  
  3.     private static Employee instance = null;  
  4.     private Employee() {}  
  5.     public static Employee GetInstance {  
  6.         get {  
  7.             if (instance == null) {  
  8.                 instance = new Employee();  
  9.             }  
  10.             return instance;  
  11.         }  
  12.     }  
  13. }   
In the code given above, we are using a static property named as Instance for getting the instance outside of the class without using its object; and inside this property, we are checking if the instance is already created or not. If it is first time request, then we are creating an instance. We can also use method instead of property as below.
  1. public static Employee GetInstance()  
  2. {  
  3.     if (instance == null) {  
  4.         instance = new Employee();  
  5.     }  
  6.     return instance;  
  7. }   
So now, Employee class has only one constructor which is private so we can’t create instance using new keyword outside of the class

C#
And also, we can’t inherit this class into another class because of a private constructor.

C#
Now, we can use instance property many times and will check the instances are same or not as below. 
  1. static void Main(string[] args)  
  2. {  
  3.     Employee emp1 = Employee.GetInstance;  
  4.     Employee emp2 = Employee.GetInstance;  
  5.     if (emp1 == emp2) {  
  6.         Console.WriteLine("Same instances");  
  7.     } else {  
  8.         Console.WriteLine("Different instances");  
  9.     }  
  10.     Console.ReadLine();  
  11. }   
Output

C#
The first approach is good but it is not thread safe. Let's assume that first time two different threads will evaluate the if condition at the same time for checking if the instance is null or not, and for both the cases, it will return true because till now no instance is created. So, both threads will enter into the if condition and create new instances. It is a violation of singleton design pattern.
To overcome this situation, we have to write threads safety program as below.
Second approach 
  1. public class Employee {  
  2.     private static Employee instance = null;  
  3.     private static readonly object instanceLock = new object();  
  4.     private Employee() {}  
  5.     public static Employee GetInstance {  
  6.         get {  
  7.             lock(instanceLock) {  
  8.                 if (instance == null) {  
  9.                     instance = new Employee();  
  10.                 }  
  11.                 return instance;  
  12.             }  
  13.         }  
  14.     }  
  15. }   
This approach is thread safe because at one time, only one thread can enter inside the lock block. Multiple threads can not access GetInstance at the same time that means it is a slow approach.
To overcome this situation, we have to write double-check locking program as below.
Third approach 
  1. public class Employee  
  2. {  
  3.     private static Employee instance = null;  
  4.     private static readonly object instanceLock = new object();  
  5.     private Employee() {}  
  6.     public static Employee GetInstance {  
  7.         get {  
  8.             if (instance == null) {  
  9.                 lock(instanceLock) {  
  10.                     if (instance == null) {  
  11.                         instance = new Employee();  
  12.                     }  
  13.                 }  
  14.             }  
  15.             return instance;  
  16.         }  
  17.     }  
  18. }   
In this approach, firstly we are checking if (instance == null ) every time hence after creating an instance of the class first time. So, from second time onwards, it will not go inside of the first if block and return existing instance, but in the case of very first time, suppose two threads will come at the same time to access first if statement and get true value and enter into the if block, then also, only one thread can enter into the lock statement and wait for other thread to complete task.
So, after completion of the task of first thread, when the second thread will enter inside the lock block it will check again if(instance==null); and at this time, we already have instance which is created by first thread, so it will not allow inside the second if block and will return existing instance.
We are going to see the same thing without using if condition or lock in our next approach.
Fourth approach 
  1. public class Employee  
  2. {  
  3.     private static readonly Employee instance = new Employee();  
  4.     private Employee() {}  
  5.     public static Employee GetInstance {  
  6.         get {  
  7.             return instance;  
  8.         }  
  9.     }  
  10. }   
This is very simple and thread safe approach. It is called as Static initialization or Early instance creation. Singleton Design pattern is very useful for the logger implementation in our application and this is the famous design pattern.
In this article, we have covered the basic understanding of Singleton design pattern.

No comments:

Post a Comment