Singleton Design Pattern is a creational design pattern. It is one of the common design patterns used to design software applications.

What is Singleton Design Pattern?

Basic needs of Singleton Design Pattern?

Quick On Singleton Design Pattern

Advantages

Disadvantages

How to implement it?

There are many ways to implement a singleton design pattern. Here, I will demonstrate the best practices to implement a singleton design pattern.

Option A

Below code defines the singleton code for Logger by using .NET Lazy type. The initialization of the object happens on demand only. The caller code calls the singleton logger with 10 times and has the same instance all the 10 times call with having the same hash code.

Implementation Code

public sealed class SingletonLogger {  
    private static readonly Lazy<SingletonLogger> _singletonLoggerObj = new Lazy<SingletonLogger> (() => new SingletonLogger());  
    private SingletonLogger() {}  
    public static SingletonLogger SingletonLoggerInstance {  
        get {  
            return _singletonLoggerObj.Value;  
        }  
    }  
}  

Client Code

List<int> hashData = new List<int>();  
for (int index = 0; index < 10; index++)
    hashData.Add(SingletonLogger.SingletonLoggerInstance.GetHashCode());  

if (hashData.Distinct().Count() == 1)
     Console.WriteLine("I am Singleton!");  
else
     Console.WriteLine("I am not Singleton!");  

Output

Quick On Singleton Design Pattern

Option B

When multiple parallel threads access the same instance at the same time to get an instance of a singleton logger, there may be a concurrency conflict on creating an instance and violating the singleton pattern.

The below code defines the singleton code for Logger that is thread-safe. When multiple parallel threads access code at the same time to get an instance of a singleton logger. The code defines a lock pad object to prevent the concurrency issue while creating a singleton instance.

Implementation Code

public sealed class SingletonLoggerThreadSafe {  
    private static readonly object _objLock = new object();  
    private static SingletonLoggerThreadSafe _instance = null;  
    private SingletonLoggerThreadSafe() {}  
    public static SingletonLoggerThreadSafe Instance {  
        get {  
            if (_instance == null) {  
                lock(_objLock) {  
                    if (_instance == null)
                        _instance = new SingletonLoggerThreadSafe();  
                }  
            }  
            return _instance;  
        }  
    }  
}  

Client Code

static void Main(string[] args) {  
    // By using - SingletonLoggerThreadSafe  
    Task<int> task1 = Task.Run(ThreadBatch1);  
    Task<int> task2 = Task.Run(ThreadBatch2);  
    if (task1.Result == task2.Result && task1.Result != -1)
        Console.WriteLine("I am Singleton!");  
    else
        Console.WriteLine("I am not Singleton!");

    Console.ReadLine();  
}  
public static int ThreadBatch1() {  
    int val = -1;  
    List<int> hashData = new List<int> ();  
    for (int index = 0; index < 50000000; index++)
         hashData.Add(SingletonLoggerThreadSafe.Instance.GetHashCode()); 

    var res = hashData.Distinct();  
    if (res.Count() == 1) {  
        Console.WriteLine("ThreadBatch1 - I am Singleton!");  
        val = res.First();  
    } 
    else
        Console.WriteLine("ThreadBatch1 - I am not Singleton!");  
    return val;  
}  
public static int ThreadBatch2() {  
    int val = -1;  
    List<int> hashData = new List<int>();  
    for (int index = 0; index < 50000000; index++)
        hashData.Add(SingletonLoggerThreadSafe.Instance.GetHashCode()); 

    var res = hashData.Distinct();  
    if (res.Count() == 1) {  
        Console.WriteLine("ThreadBatch2 - I am Singleton!");  
        val = res.First();  
    }
    else
        Console.WriteLine("ThreadBatch2 - I am not Singleton!");  
    return val;  
}  

Output

Quick On Singleton Design Pattern

Conclusion

Both of the above options are recommended. Personally, I would prefer Option A that takes advantage of lazy initialization.

Note
This is one of the common design pattern interviewers as in design pattern interview questions. 😊