Singleton: How should it be used

Edit: From another question I provided an answer that has links to a lot of questions/answers about singletons: More info about singletons here:

So I have read the thread Singletons: good design or a crutch?
And the argument still rages.

I see Singletons as a Design Pattern (good and bad).

The problem with Singleton is not the Pattern but rather the users (sorry everybody). Everybody and their father thinks they can implement one correctly (and from the many interviews I have done, most people can't). Also because everybody thinks they can implement a correct Singleton they abuse the Pattern and use it in situations that are not appropriate (replacing global variables with Singletons!).

So the main questions that need to be answered are:

  • When should you use a Singleton
  • How do you implement a Singleton correctly
  • My hope for this article is that we can collect together in a single place (rather than having to google and search multiple sites) an authoritative source of when (and then how) to use a Singleton correctly. Also appropriate would be a list of Anti-Usages and common bad implementations explaining why they fail to work and for good implementations their weaknesses.


    So get the ball rolling:
    I will hold my hand up and say this is what I use but probably has problems.
    I like "Scott Myers" handling of the subject in his books "Effective C++"

    Good Situations to use Singletons (not many):

  • Logging frameworks
  • Thread recycling pools
  • /*
     * C++ Singleton
     * Limitation: Single Threaded Design
     * See: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
     *      For problems associated with locking in multi threaded applications
     *
     * Limitation:
     * If you use this Singleton (A) within a destructor of another Singleton (B)
     * This Singleton (A) must be fully constructed before the constructor of (B)
     * is called.
     */
    class MySingleton
    {
        private:
            // Private Constructor
            MySingleton();
            // Stop the compiler generating methods of copy the object
            MySingleton(MySingleton const& copy);            // Not Implemented
            MySingleton& operator=(MySingleton const& copy); // Not Implemented
    
        public:
            static MySingleton& getInstance()
            {
                // The only instance
                // Guaranteed to be lazy initialized
                // Guaranteed that it will be destroyed correctly
                static MySingleton instance;
                return instance;
            }
    };
    

    OK. Lets get some criticism and other implementations together.
    :-)


    All of you are wrong. Read the question. Answer:

    Use a Singleton if:

  • If you need to have one and only one object of a type in system
  • Do not use a Singleton if:

  • If you want to save memory
  • If you want to try something new
  • If you want to show off how much you know
  • Because everyone else is doing it (See cargo cult programmer in wikipedia)
  • In user interface widgets
  • It is supposed to be a cache
  • In strings
  • In Sessions
  • I can go all day long
  • How to create the best singleton:

  • The smaller, the better. I am a minimalist
  • Make sure it is thread safe
  • Make sure it is never null
  • Make sure it is created only once
  • Lazy or system initialization? Up to your requirements
  • Sometimes the OS or the JVM creates singletons for you (eg in Java every class definition is a singleton)
  • Provide a destructor or somehow figure out how to dispose resources
  • Use little memory

  • Singletons give you the ability to combine two bad traits in one class. That's wrong in pretty much every way.

    A singleton gives you:

  • Global access to an object, and
  • A guarantee that no more than one object of this type can ever be created
  • Number one is straightforward. Globals are generally bad. We should never make objects globally accessible unless we really need it.

    Number two may sound like it makes sense, but let's think about it. When was the last time you **accidentally* created a new object instead of referencing an existing one? Since this is tagged C++, let's use an example from that language. Do you often accidentally write

    std::ostream os;
    os << "hello worldn";
    

    When you intended to write

    std::cout << "hello worldn";
    

    Of course not. We don't need protection against this error, because that kind of error just doesn't happen. If it does, the correct response is to go home and sleep for 12-20 hours and hope you feel better.

    If only one object is needed, simply create one instance. If one object should be globally accessible, make it a global. But that doesn't mean it should be impossible to create other instances of it.

    The "only one instance is possible" constraint doesn't really protect us against likely bugs. But it does make our code very hard to refactor and maintain. Because quite often we find out later that we did need more than one instance. We do have more than one database, we do have more than one configuration object, we do want several loggers. Our unit tests may want to be able to create and recreate these objects every test, to take a common example.

    So a singleton should be used if and only if, we need both the traits it offers: If we need global access (which is rare, because globals are generally discouraged) and we need to prevent anyone from ever creating more than one instance of a class (which sounds to me like a design issue). The only reason I can see for this is if creating two instances would corrupt our application state - probably because the class contains a number of static members or similar silliness. In which case the obvious answer is to fix that class. It shouldn't depend on being the only instance.

    If you need global access to an object, make it a global, like std::cout . But don't constrain the number of instances that can be created.

    If you absolutely, positively need to constrain the number of instances of a class to just one, and there is no way that creating a second instance can ever be handled safely, then enforce that. But don't make it globally accessible as well.

    If you do need both traits, then 1) make it a singleton, and 2) let me know what you need that for, because I'm having a hard time imagining such a case.


    The problem with singletons is not their implementation. It is that they conflate two different concepts, neither of which is obviously desirable.

    1) Singletons provide a global access mechanism to an object. Although they might be marginally more threadsafe or marginally more reliable in languages without a well-defined initialization order, this usage is still the moral equivalent of a global variable. It's a global variable dressed up in some awkward syntax (foo::get_instance() instead of g_foo, say), but it serves the exact same purpose (a single object accessible across the entire program) and has the exact same drawbacks.

    2) Singletons prevent multiple instantiations of a class. It's rare, IME, that this kind of feature should be baked into a class. It's normally a much more contextual thing; a lot of the things that are regarded as one-and-only-one are really just happens-to-be-only-one. IMO a more appropriate solution is to just create only one instance--until you realize that you need more than one instance.

    链接地址: http://www.djcxy.com/p/8824.html

    上一篇: 我如何从另一个线程更新GUI?

    下一篇: 辛格尔顿:应该如何使用它