The Singleton Pattern is something many people have used without even realising it. It’s used in software engineering to restrict the instantiation of a class to one object. In other words, it ensures that a class has only one instance and provides a global point of access to that instance.

In other…other words it’s useful in situations where you need to ensure that only one instance of a class exists and that it is easily accessible to other parts of your code.

A good example would be a logging system that needs to be accessed by multiple components. You use a singleton to sure that there is only one instance of the logging system, and that all components access the same instance.

Coding Examples

C# Example

Here’s a simple example of how to implement the Singleton Pattern in C#:

public class Singleton
{
    private static Singleton instance;
    
    private Singleton()
    {
        // Private constructor to prevent object instantiation from outside the class
    }
    
    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

Here we see Singleton has a private constructor to prevent object instantiation from outside the class. Instead, we use the Instance property to access the class:

Singleton instance = Singleton.Instance;

That’s as simple as it gets!

C++ Example

In C++ things become a bit more intricate:

#include <iostream>

using namespace std;

// Singleton class
class Singleton {
public:
    // Delete the copy constructor and assignment operator
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    // Static method to get the instance of the singleton
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }

    // Example method
    void showMessage() {
        cout << "Hello, this is a singleton instance!" << endl;
    }

private:
    // Private constructor to prevent instantiation
    Singleton() {
        cout << "Singleton instance created." << endl;
    }

    // Destructor
    ~Singleton() {
        cout << "Singleton instance destroyed." << endl;
    }
};

int main() {
    // Get the single instance of the singleton class
    Singleton& singleton = Singleton::getInstance();

    // Call a method on the singleton instance
    singleton.showMessage();

    return 0;
}

Let’s explain things a bit:

  1. Private Constructor and Destructor: The constructor and destructor of the Singleton class are private to prevent direct instantiation and destruction.
  2. Deleted Copy Constructor and Assignment Operator: The copy constructor and assignment operator are deleted to prevent copying of the singleton instance.
  3. Static Method for Access: The getInstance static method provides a global point of access to the singleton instance. It uses a local static variable to ensure that only one instance is created and it is destroyed when the program terminates.
  4. Example Method: The showMessage method is an example method that can be called on the singleton instance.

Python Example

In Python we have more than one ways of achieving this, let’s look at a more complex example first:

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self):
        self.value = None

    def show_message(self):
        print("Hello, this is a singleton instance!")

# Usage
singleton1 = Singleton()
singleton2 = Singleton()

print(singleton1 is singleton2)  # True
singleton1.show_message()  # Hello, this is a singleton instance!

This method gives you a lot of control over how the singleton is instantiated, though it is complex to understand at first and I find myself referencing it time and again.

A different method would be using a decorator:

def singleton(cls):
    instances = {}
    
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    
    return get_instance

@singleton
class Singleton:
    def __init__(self):
        self.value = None

    def show_message(self):
        print("Hello, this is a singleton instance!")

# Usage
singleton1 = Singleton()
singleton2 = Singleton()

print(singleton1 is singleton2)  # True
singleton1.show_message()  # Hello, this is a singleton instance!

This is more concise and easy to understand.

My favourite method though, is using a module:

# singleton_module.py
class Singleton:
    def __init__(self):
        self.value = None

    def show_message(self):
        print("Hello, this is a singleton instance!")

singleton = Singleton()

# Usage in another file
# import singleton_module

# singleton1 = singleton_module.singleton
# singleton2 = singleton_module.singleton

# print(singleton1 is singleton2)  # True
# singleton1.show_message()  # Hello, this is a singleton instance!

In Python, modules are singletons by design, meaning that they are only loaded once and the same instance is used throughout the application.

Thread-safety

Something I neglected to touch on in the C# example was that it was fine and well, in a single-threaded environment. If we move to multiple threads this class might not be very safe to use. I’m not going to address thread safety, as a concept, in this article but a simple way to make this singleton thread safe would be as follows:

public sealed class Singleton
{
    private static volatile Singleton instance;
    private static object syncRoot = new object();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

Here we used the double-check locking technique and the Singleton classic is made thread-safe by using the lock statement to ensure that only one threat at a time can create the instance of the class.

The volatile keyword tells the compiler to exclude the property from various optimisations and ultimately ensures the value of instance is always up-to-date across different threads.

The double-check locking technique is used to minimise the performance impact of the lock statement. We can implement the class similarly using something like semaphores.

A final note is that this implementation is lazy-loaded. In other words, the Singleton is not instantiated until it is requested. You could easily create it eagerly by initialising the instance field when it is declared.