Home » Blog » Singleton Design Pattern

Singleton Design Pattern

singleton-design-pattern

Singleton is a creational design pattern that ensures that a class has only one instance and provides a global point of access to that instance.

In plain simple words – Singleton is a way of making sure that a specific class can only have one object created from it at any given time. It also gives an easy way for any part of the program to access this single object.

In this blog post, we’ll take a look at what the Singleton pattern is, when to use it, and how to implement it in .NET.

Usage

The Singleton pattern is often used for objects that manage resources or configuration settings. For example, a database connection or a configuration object might only need one instance to be shared among all the objects in an application.

The Singleton pattern ensures that only one instance of the object is created and that it is accessible to all parts of the application.

Implementation

All versions of the Singleton pattern follow these two common steps:

  • To prevent other objects from creating new instances of a Singleton class, make the default constructor of the class private.
  • Create a static method that can create an object of the class, this method will be used instead of the constructor. This method will call the private constructor to create an object, save it in a static field, and will return this object for any subsequent calls.

Code

Here’s an example of how to implement the Singleton pattern in C#:

public sealed class Singleton
{
    private static Singleton _instance;
    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }
    }
    public void BusinessLogicMethod()
    {
        // ...
    }
}

In this code, the class Singleton is defined with a private constructor to prevent other objects from creating an instance of the class. It also has a private static variable _instance to hold the only instance of the class.

The Instance property is a public static property, which serves as a global point of access to the Singleton instance, it creates an instance of the class if it doesn’t exist yet and return the existing instance if it already exists.

The BusinessLogicMethod method is an example of a method that can be used on the singleton instance.

Let’s consume the Singleton instance:

class Program
{
    static void Main(string[] args)
    {
        Singleton first = Singleton.Instance;
        Singleton second = Singleton.Instance;

        if (first == second)
        {
            Console.WriteLine("Singleton works, both variables contain the same instance.");
        }
        else
        {
            Console.WriteLine("Singleton failed.");
        }
    }
}

In this method, two variables first and second are created and assigned to the Singleton instance by calling the Singleton.Instance property.

Then, it compares the two variables to check if they are the same instance, if so the program prints “Singleton works” otherwise it prints “Singleton failed”

It’s worth noting that by using the Singleton.Instance property, we are guaranteed that the two variables first and second will always contain the same instance, this is because the Singleton.Instance property ensures that only one instance of the class is created, and it returns this instance every time it’s called.

Code Output:

Singleton works, both variables contain the same instance.

Thread Safe Singleton

The code above is not thread-safe because it doesn’t prevent multiple threads from creating multiple instances of the Singleton class at the same time.

The problem is that the if (_instance == null) check is not atomic, two different threads might both see the _instance variable as null and then both create a new instance of the Singleton class.

This can lead to multiple instances of the Singleton class being created, which breaks the Singleton’s contract that only one instance should exist.

To fix this, we need to make sure that only one thread can create an instance at a time, this can be done by using a lock statement.

class Singleton
    {
        private Singleton() { }

        private static Singleton _instance;

        private static readonly object _lock = new object();

        public static Singleton GetInstance(string value)
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                        _instance.Value = value;
                    }
                }
            }
            return _instance;
        }
        public string Value { get; set; }
    }

The class Singleton has a private constructor to prevent other objects from creating an instance of the class.

It also has a private static variable _instance to hold the only instance of the class.

The _lock object is used as a synchronization object to ensure that only one thread can enter the critical section of the code at a time.

The GetInstance method is a public static method, which serves as a global point of access to the Singleton instance, it creates an instance of the class if it doesn’t exist yet and return the existing instance if it already exists.

The method takes an argument value that can be set to the singleton instance Value property. This method uses a double-checked locking mechanism to ensure that only one instance of the class is created, even in a multithreaded environment.

Let’s consume the thread safe singleton code:

class Program
    {
        static void Main(string[] args)
        {
            var message1 = "If we see the same value, then the same singleton instance was reused.";
            var message2 = "If we see different values, then two singleton instances were created.";

            Console.WriteLine("{0}\n{1}\n{2}\n", message1, message2, "OUTPUT:");

            Thread processA = new(() =>
            {
                TestSingleton("Pasta");
            });
            Thread processB = new(() =>
            {
                TestSingleton("Sandwich");
            });
            
            processA.Start();
            processB.Start();
            
            processA.Join();
            processB.Join();
        }
        
        public static void TestSingleton(string value)
        {
            Singleton singleton = Singleton.GetInstance(value);
            Console.WriteLine(singleton.Value);
        } 
    }

In this method, two threads are created, processA, and processB. Each thread calls the TestSingleton method and passing a different string value to it.

The TestSingleton method creates a variable singleton and assigns it to the Singleton instance by calling the Singleton.GetInstance method, passing the value variable to it. After that, the method writes the value of the singleton instance to the console.

The main method starts the two threads and waits for them to complete using the Join method.

The output of the program will display the values passed to the singleton instances, and if they are the same, it means that the singleton instance was reused, if they are different it means that two singleton instances were created.

Code Output:

If we see the same value, then the same singleton instance was reused.
If we see different values, then two singleton instances were created.
OUTPUT:

Pasta
Pasta

Conclusion

In conclusion, the Singleton pattern is a useful pattern when only one instance of a class is needed, to manage resources or configuration settings.

It ensures that the class can only be instantiated once and provides a global point of access to that instance.

1 thought on “Singleton Design Pattern”

  1. Pingback: Simple Factory Design Pattern - TechnCode Tools

Leave a Reply

Your email address will not be published. Required fields are marked *