The Singleton pattern

· Read in about 5 min · (968 Words)

As described in «Design Patterns: Elements of Reusable Object-Oriented Software» by Erich Gamma, et al. the Singleton pattern describes a solution to create a class that will have one and only one instance within an application and also provide a global access to it. Even though there are many arguments against using it, the Singleton is still widely used.

So what can I use it for? Caching, logging, and any other shared resource access. I will attempt to explain some sample implementations and issues with the pattern. Remember - there is no «right» implementation. Whatever fits your needs is the right implementation. For simplicity I will focus on single threaded implementations.

It is important to understand the issues with each implementation in order to use is properly (or make your own).

Sample Implementations

A first implementation might look as:

// A naive first implementation

// In the header file
class Singleton
{
private:
    // Private Constructor
    Singleton();
    static Singleton* _instance;

public:
    static Singleton* Instance();
};

// in the implementation file
Singleton* Singleton::_instance = nullptr;

Singleton* Singleton::Instance()
{
    if (_instance == nullptr) {
        _instance = new Singleton;
    }
    return _instance;
}

There are some problems with this implementation:

  • Who will delete the instance if it is created?
  • The Instance() function returns a pointer - what happens if someone deletes it?
  • Someone might write Singleton moo(*Singleton::Instance()); and that will break the singleness of the class.

Here is a second implementation which overcomes many of the disadvantages of the first implementation.

// A better Singleton implementation

class Singleton
{
private:
    // Private Constructor
    Singleton();
    Singleton(Singleton&); // no implementation
    Singleton& operator= (Singleton const&); // no implementation

public:
    static Singleton& Instance()
    {
        static Singleton instance; 
        return instance;
    }
};

This implementation solves the problems with the first implementation:

  • Now empty copy constructor and assignment operator prevent copying the Singleton object
  • Instance() returns a reference
  • The Singleton is destroyed properly
  • It is still lazily initialized (is this compiler dependent?)

What can be improved here? Any  problems?

Here is what problems are still there:

  • We have a problem if another static object hangs onto a reference of the singleton and calls it after the Singleton is destroyed. You can read some solutions in Andrei Alexandrescu’s «Modern C++ design».
  • I usually like to have objects allocated on the heap, not the stack
  • Only works with a default constructor

With the C++ 11 standard and its implementation in the various compilers we can now write a little bit nicer singletons:

// A C++11 implementation 

class Singleton
{
private:
    // Private Constructor
    Singleton();
    Singleton(Singleton&) = delete; // no implementation
    Singleton& operator= (Singleton const&) = delete; // no implementation

public:
    static Singleton& Instance()
    {
        static std::unique_ptr<Singleton>(new Singleton());
        return *instance.get();
    }
};

Bonus: C++ 11 states that the initializer for a local static variable is only run once, even when concurrently run. You still need to make sure that the actual class functionality is thread safe.

This implementation still doesn’t solve the issue with someone keeping a reference to it in a static object and tries to use it after it is released, but in many cases I’d trade this safety for simplicity. It also still uses the default constructor, which might not be a desired behavior.

Drawbacks

While it provides very convenient access to shared resources (Application Configuration, State, Data Caches, etc.) all available at the effort of a single #include and not using any resources or initialization until used, the Singleton may have some unintended at first glance consequences.

It is global after all

Why we avoid using global variables? Is Singleton better? A little bit better in my opinion, but you still need to be careful using it. I know we are all adults, but someone can inadvertently tightly couple code that you were very careful for years to be separate.

  • Difficult to mock in Unit tests
  • May be difficult to parallelize
  • Can’t sub-class/use abstract interfaces

This makes IoC very difficult. Imagine you stored all your data in MS Access and were using a singleton now would like to support SQL Server as well? You would have some refactoring on your hands that may not be an hour job.

Never explicitly initialized/freed

As a C++ programmer you want to be in control! You need to be able to control when is something instantiated, initialized or destroyed in order to control the timing of the usage of precious resources. The singleton takes away that ability to a large extent.

Conclusion

Although a very easy near term solution, you should very carefully choose when to use singletons and what would the long term impact be on the overall software. You could consider instead other options first (e.g. using a single instance of a class and pass a reference around) to avoid some of the issues.

What are the alternatives

Even though there are some drawbacks to the Singleton pattern, you can choose to use it (I know I do sometimes). If you don’t want to here are some alternative approaches.

A base class

You can get the things you need from a base class.

// Base Class
class Animal
{
protected:
    Configuration& Config() { return config; }

private:
    static Configuration& config;
};

class Cow : public Animal
{
    void Moo()
    {
        int boo = Config().Get("Boo");
    }
};

A parameter

You could pass a reference around, but boy this may get tedious. Also you need to change the API every time if you need to add the object.

Do you have any global objects?

Instead of singletons, you can have an Application object, which contains all such objects, but this has its own pros and cons.

// Use a global object
class Application
{
public:
    static Application& App() { return application; }

    Configuration& Config() { return *config; }

private:
    Configuration* config;
};

You need to decide what fits you best.