Design Patterns in C# - Singleton

Design Patterns in C# - Singleton

Welcome to the series on Design Patterns using C#. Today we will be looking into one of the most commonly used and implemented patterns i.e. Singleton. As part of this series we will cover most of the patterns one by one and see how it can be implemented using C#

The Singleton Pattern

Whenever we are in need of an instance of a class we use the new keyboard and create a new instance every-time. Part of the Gang of Four design patterns, Singleton is used to the restrict the instantiation of class to only one object.

It is the responsibility of the class implementing the Singleton pattern to make sure that only a single instance is created for it and also that the instance is available for everyone requiring.

This is done by creating the instance only when it is requested for the first time, and going forward for each subsequent request, the same object is returned.

image.png

Properties of a Singleton Class

  • The class firstly declares a private instance variable so that the it cannot be accessed externally
  • Constructor of the class is then marked as private as we want to restrict calling it using the new keyword to create an instance
  • Finally we declare a public static method which returns an instance of that class to the caller. This makes the method the sole access point for getting an instance of the class
  • We don't normally inherit a singleton class but in case it is required then making the constructor protected should fix that

Implementation

Singleton pattern can be utilised most effectively when we are dealing with system wide data. Data that doesn't change based on the class or the reference. For the sake of our implementation lets consider a logger class which is used to log items into a log file. We want this class to be singleton as the same file and same object should be used to log throughout the app

public class SingletonLogger
{
    private static SingletonLogger singleInstance;
    private SingletonLogger() {}

    public static SingletonLogger GetInstance()
    {
        if (singleInstance == null)
            singleInstance = new SingletonLogger();
        return singleInstance;
    }

    public void LogError(string exceptionMsg) {
        try {
            // logging logic
        }
        catch(exception ex){
            // exception handling logic
        }
    }

}
  • The GetInstance() method check if we already have an instance object available. If not we create a new one or else we just send back the existing one making sure we only have one instance running throughout the entire app

Limitations

Due to the way singleton pattern is implemented, it is sometime considered as an anti-pattern. We don't have the knowledge if the instance is new one or an existing one and also it prevents dependency injection.

Since there is only a single instance of the class floating around, injecting a dependency wont be possible. This further prevents Test Driven Development (TDD) approach for such classes which heavily relies on DI.

Did you find this article valuable?

Support Rajat Srivastava by becoming a sponsor. Any amount is appreciated!