8

I read the article Abstract Factory, Template Style by Jim Hyslop and Herb Sutter. This factory is implemented as a Singleton. They provided an easy way to register classes automatically with the RegisterInFactory helper class.

Now i've read several times that Singletons should be avoided, some even consider them as Anti-Patterns and that there are just a few cases where they are usefull. Is this one of them? Or is there an alternative approach which provides such an easy way to autoregister classes?

P3trus
  • 103
  • 4
  • I'm curious to know where from you refer that "Singletons should be avoided"... – YeenFei Jan 19 '11 at 10:14
  • "Singletons should be avoided" just like global variables. An Abstract Factory is more like a global service. After initialisation (Registration) all clients only read from it (ask for objects). I think the Abstract Factory is one of the cases where a Singleton is usefull. – hansmaad Jan 19 '11 at 10:26
  • i.e. http://stackoverflow.com/questions/86582/singleton-how-should-it-be-used or http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx – P3trus Jan 19 '11 at 10:27
  • 1
    @hansmaad: sounds to me like one of the cases where *globals* are useful. I see no reason why it'd be beneficial to make it a singleton as well. – jalf Jan 19 '11 at 16:12
  • 1
    @YeenFei: http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/ for example. Of course, if you google "singletonitis" or "singleton antipattern" or "singletons considered harmful", you'll find dozens more. – jalf Jan 19 '11 at 16:13
  • @jalf late answer, but... last week a colleague used a global variable for the factory and felt into the trap of the 'static initialization order fiasco'. The benefit of the local static (singleton) instance is the initialization on first registrration. – hansmaad Dec 11 '11 at 18:47
  • @hansmaad: But you're treating the symptom, not the cause. The problem is that your entire program takes place outside the `main` function. Why do you have globals whose initialization depend on other globals? Sure, if you insist on making half your program global, then you need to pull out the big (and overly complex and error-prone) guns, but that doesn't mean singletons are a good tool; it merely means that you need to trim down the amount of global state in your app – jalf Dec 11 '11 at 19:18
  • Furthermore, what you need, according to your description, is only *part* of what a singleton gives you. You need a lazily initialized global. A singleton does that, sure, but it *also* walls you in, and prevents you from *ever* creating another instance of that type. And that's a harmful, and unnecessary constraint to plaster across your code when all you needed was a global whose initialization is deferred. – jalf Dec 11 '11 at 19:19

1 Answers1

2

As ever for this sort of subject, there is no answer that applies to every problems. Some said that singleton should be avoided when they are used as an access to a service. It is a use that is akin to the use of global variables. This way you mask the fact that you use service X in your implementation :

// in header
class MyUsefulClass
{
    public:
    void doSomethingUseful();
};

// in .cpp
MyUsefulClass::doSomethingUseful()
{
    // ...
    MyWonderfulService::instance().doService1();
    // ...
    MyWonderfulService::instance().doService2();
}

You create a coupling with MyWonderfulService that the users of your class can not guess. Moreover, You can not easily test your useful class with a mock service ...

That's why I usually prefer dependancy inversion :

// in header
class MyUsefulClass
{
    public:
    void setServiceToUse(MyService&);
    void doSomethingUseful();

    // [...]
};

// in .cpp
MyUsefulClass::doSomethingUseful()
{
    // ...
    _myService->doService1();
    // ...
    _myService->doService2();
}

This way is usually considered better as the coupling between class is lighter. Nevertheless, for some services, which are well known to be of widespread use in a framework, it is simplier to use a singleton. It makes sense for a single service that is the service which give you access to all other services in a framework for example ^^ It is often use for technical services like logging for instance.

my2c

Edit: I read the article, as the focus is on AbstractFactories, the use of a singleton is a casual one, not a design decision. It is understandable in an article in which you do not want to write things that will not get you to your point.

neuro
  • 14,948
  • 3
  • 36
  • 59
  • So to have the autoregistration as shown in the article i need the global access but i don't need it to be the only instance. An alternative would therefore be to provide it as a global like std::cout which alows me to use it, but doen't prevent me from using a second one if needed. Or is there a third way, maybe superior way to achieve this autoregistration? – P3trus Jan 19 '11 at 11:45
  • @p3trus: I will add a concrete example in my answer when I have time ... Just try a global for now. I personnaly use depandancy inversion everytime ... – neuro Jan 21 '11 at 09:56