The Singleton Pattern

The Singleton Pattern is one of the patterns listed in the famous book Gang of Four Design Patterns Book. It is probably the most common design patterns that I have seen on code that I have worked on.

It is also considered by many as an anti-pattern.

Introduction

class MySingleton
{
public:
    static MySingleton* instance() {
        if (m_instance == nullptr) {
            m_instance = new MySingleton();
        }
        return m_instance();
    }

    <other methods>

private:
    MySingleton(); //Needs to be private. Ensure only instance can create it
    ~MySingleton(); //Object must not accidentally get deleted during normal
                    //operation
    static MySingleton* m_instance;

    <other attributes>
};

The singleton class can the be easily accesses from any part of the code with the simply by

int val = MySingleton::instance()->getValue();

It is this simple way of accessing the Singleton that makes it so popular. If I want to write to my logger file, I can just write

Logger::instance()->writeData();

Simple.

In a nutshell, a Singleton is a global variable by another name. This is clear from the line

static MySingleton* m_instance

Static variables in classes are global variable. And since the instance is global, so is the class.

The main benefit over a straight out global variable is that it has lazy instantiation, so if you control the order of first access, you can control the order of instantiation. However in a large system, this is less of a benefit that you think as I will describe shortly.

So why all the hate?

A Singleton by its very nature allows only a single instance to exist throughout the entire program. This might be fine in a small program. But small programs do evolve and become much bigger program.

You then find that there might be cases where you want peek at a new state without overriding the old. Or where in the beginning you only supported one client instance and now you need to support more. These cases then require a major change to your program’s architecture.

2. No ownership

A Singleton is owned by the global space of the program so your Singleton object has no real owner. Different Singleton objects can interact with each other and change each other’s state without any form of control.

This makes reasoning about what happens where and why difficult. It also makes it difficult to sensibly notify a parent that a change has happened since the Singleton has no parent.

If you want to access a non-Singleton object, you either must have a reference to it yourself or you get one from its parent. Without a reference to the object, the object is totally inaccessible.

This make reasoning about who can make changes to my object a whole lot easier.

3. Where does it belong?

When designing a program we create a number of object classes. For each class, we have some idea of what it is supposed to do and how we interact with it. Yet as we expand a project we will find it difficult to choose which object should own a given functionality.

For non-Signelton classes this is easy. We put this functionalty where we can get at it easily. We allow our object model (which control’s accessibity to guide us. For Singletons, we have no such luck. Every Singleton is accessible from everywhere.

Conclusion

Singleton do provide easy access to a global facility. But like most things, what might be easy to use now but by breaking down some of the barriers, end up with something that can be very hard to use.