Singleton Design Pattern

Singleton Design Pattern

With this post a brand-new series about Software Design Patterns starts. You will learn everything about the most used Design Patterns. The first is probably the most known. It is the Singleton Design Pattern. It is one of the twenty-three well-known - and industry standard - Gang of Four Design Pattern Collection.

All the examples, source code and unit tests are in this GitHub repository.

What's the purpose of the Singleton Design Pattern?

In software development we often instantiate a class many times. This could be problematic. As a result you have to deal with many instances of the very same class. This introduces complexity and increases memory usage of the application.

The Singleton Design Pattern solves this specific issue. It ensures that only one instance of this class exists. Beyond that it standardizes and eases the access to that instance. To access the instance a Singleton provides per design a static `GetInstance()` method. To prevent any instantiating via the new keyword you have to hide the constructor.

How does the Singleton Design Pattern looks like?

In the picture below you find the Unified Modeling Language (UML) diagram.

Singleton Definition

The very basic implementation doesn't care about thread-safety. It's called BasicSingleton within the GitHub Repository.

public class BasicSingleton
{
    public string Name => "Singleton";
    private static BasicSingleton instance;
    
    private BasicSingleton(){ }

    public static BasicSingleton GetInstance()
    {
        if(instance == default(BasicSingleton)){
                instance = new BasicSingleton();
        }

        return instance;
    }
}

How about Thread-Safety?

This implementation could lead to problems when many threads calls the GetInstance() simultaneously. For example the second thread enters the if condition while the first isn't finished yet. Thus, a second instance will be created. This behavior violates the Singleton Design Pattern definition. The ThreadSafeSingleton prevents those race conditions with locking the access to a thread at a time. This guarantees that only one instance will ever be created. Keep in mind that every time we access the Singleton we perform a lock which uses a bit more resources.

public class ThreadSafeSingleton
{
    public string Name => "Singleton";
    private static ThreadSafeSingleton instance;
    private static readonly object singletonlock = new object();  
    
    private ThreadSafeSingleton(){ }

    public static ThreadSafeSingleton GetInstance()
    {
        lock (singletonlock)  
        {  
            if(instance == default(ThreadSafeSingleton))
            {
                instance = new ThreadSafeSingleton();
            }

            return instance;
        }          
    }
}

That’s it. Happy coding as always :).