vendredi 14 décembre 2018

C++ Singletons: how good is this solution? Advantages/disadvantages, alternatives

I am working on a C++ project having multiple classes that must be singletons, with dependencies between them (order of initialization matters).

I have come up with this solution:

  1. All classes which I want to be singletons have protected constructors, e.g.:
class MySingleton1
{
protected:
    MySingleton1();
}

  1. Have a source file singleton_factory.cpp containing an instantiated class Singletons which derives from all classes which I want to be singletons, like this:
#include "MySingleton1.hpp"
#include "MySingleton2.hpp"

class Singletons : public MySingleton1, public MySingleton2 {}
static Singletons s_singletons;

  1. Still in singleton_factory.cpp, for every singleton type, also implement a specialization of a getSingleton function:
template<>
MySingleton1& getSingleton()
{
    return s_singletons;
}

template<>
MySingleton2& getSingleton()
{
    return s_singletons;
}

  1. The specializations of getSingleton will be "hid" under the generic templated variant, in singleton_factory.hpp:
template <class TSingleton>
TSingleton& getSingleton();

Advantages:

  • Low-coupling:

    • Singleton classes don't need to be "aware" of the Singletons class, the only need to hide their constructor under a protected qualifier (and that is not even mandatory, only good practice). The only code actually aware of the Singletons class is singleton_factory.cpp
    • Skinny dependencies for concrete instance: code that wants to use a singleton of type T only needs to include the header of type T and the skinny singleton_factory.hpp
  • Order of initialization can be controlled by changing the order of inheritance of the Singletons class

  • No lazy initialization => thread-safe?
  • getSingleton() is fast, no dynamic_cast, no reinterpret_cast

Disadvantages:

  • Every time a new singleton type appears, a getSingleton specialization, doing the same - i.e. "return s_singletons;" must be added to singleton_factory.cpp

So, as far as I can see, this is actually fairly good so I'm thinking to leave it like this, but I'm asking for your feedback (what better place to do that than the programming community?).

What extra advantages/disadvantages do you see with this solution?

What alternatives do you suggest?

Aucun commentaire:

Enregistrer un commentaire