Singleton Design pattern is also a good design pattern. Although in current world we use dependency injection heavily, so we rely on Dependency provider library (IOC container) for providing us the variable of Singleton scope.
Let's just dig straight into what is Singleton. Sometimes there are requirements to have only single instance of a class through out the life-cycle of an application (Like if we are using a printer service and multiple users are using it. Than we want only one instance of that service through out the application life-cycle. So that it's only accessible to one thread at any point of time).
Here are few characteristics of Singleton Design Pattern:
- At any time only one or no instance of Singleton class will exist.
- Singleton classes are created without parameters. (Because it contains single, private, parameter-less constructor)
- Lazy instantiation is default in Singleton Design Pattern.
- Singleton class should be sealed (We seal it using private constructor)
- A private static field holds the reference of Singleton class.
- A public static method provides access to this field.
Now let's talk about how we can create Singleton object using Singleton Pattern. Well there are different versions of Singleton design pattern, some are better than other while some only fits best for certain conditions. Let's dive into this:
First Version (Not Thread safe)
public sealed class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } }
As you can see in above code file, The constructor is private and only way to get an access to this class is through the Static Instance property, which will also provide us the only instance of this Singleton class. But there is a problem it's not thread safe.
In the getter of Instance property we are checking if instance is already created otherwise we are creating a new instance of the Singleton Class. But what happens when at the same time two threads enter the If condition. They will have 2 different instances of this Singleton class, So it's not probably a good choice to use. Let's look at a thread safe Implementation of this.
Second Version (Simple Thread safe- With Performance Impacts)
public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { lock (padlock) { if (instance == null) { instance = new Singleton(); } return instance; } } } }
The only difference b/w First Version (Thread Unsafe) & Second Version (Thread Safe) is here we are using a lock for the if condition, so only one thread will be able to enter the if condition at any point of time.
But this will mark subsequent performance impact, as every time while accessing the Singleton Class instance threads will have to go through lock and only one thread will be able to parse the code at any point of time even when the instance already exist. So we have Third Version of Singleton to remove this performance impact.
Third Version (Thread safe with double check - Performance increased)
public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (padlock) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }
Well this model works well, but still it doesn't perform well when compared to further implementations.
Forth Version (Thread safe without using locks)
public sealed class Singleton { private static readonly Singleton instance = new Singleton(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Singleton() { } private Singleton() { } public static Singleton Instance { get { return instance; } } }
Well this implementation is thread safe without using locks, but it's not as lazy as other implementations. Here we are using static constructor which will be instantiated once any instance or static member of the Singleton class will be accessed.
- If you have any other static member other than Instance property, than access to that property will involve creating instance. This is corrected in next implementation.
- There are some complications if one static member invokes another which invokes the first again.
Fifth Version (Lazy instantiated & thread safe)
public sealed class Singleton { private Singleton() { } public static Singleton Instance { get { return Nested.instance; } } private class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly Singleton instance = new Singleton(); } }
- Get link
- X
- Other Apps
- Get link
- X
- Other Apps
Comments
Post a Comment