views:

4962

answers:

19

Edit: From another question I provided an answer that has links to a lot of questions/answers about singeltons: 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.
:-)

+2  A: 

The first example isn't thread safe - if two threads call getInstance at the same time, that static is going to be a PITA. Some form of mutex would help.

Rob
Yep that is noted in the comments above: * 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
Martin York
The classic singleton with only getInstance as static method and instance methods for other operations can never be made thread safe. (well unless you make it a single-per-thread-ton using thread local storage...)
Tobi
+6  A: 

Singletons basically let you have complex global state in languages which otherwise make it difficult or impossible to have complex global variables.

Java in particular uses singletons as a replacement for global variables, since everything must be contained within a class. The closest it comes to global variables are public static variables, which may be used as if they were global with import static

C++ does have global variables, but the order in which constructors of global class variables are invoked is undefined. As such, a singleton lets you defer the creation of a global variable until the first time that variable is needed.

Languages such as Python and Ruby use singletons very little because you can use global variables within a module instead.

So when is it good/bad to use a singleton? Pretty much exactly when it would be good/bad to use a global variable.

Eli Courtwright
+1  A: 

Anti-Usage:

One major problem with excessive singleton usage is that the pattern prevents easy extension and swapping of alternate implementations. The class-name is hard coded wherever the singleton is used.

Adam Franco
+12  A: 

One thing with patterns: don't generalize. They have all cases when they're useful, and when they fail.

Singleton can be nasty when you have to test the code. You're generally stuck with one instance of the class, and can choose between opening up a door in constructor or some method to reset the state and so on.

Other problem is that the Singleton in fact is nothing more than a global variable in disguise. When you have too much global shared state over your program, things tend to go back, we all know it.

It may make dependency tracking harder. When everything depends on your Singleton, it's harder to change it, split to two, etc. You're generally stuck with it. This also hampers flexibility. Investigate some Dependency Injection framework to try to alleviate this issue.

phjr
No, a singleton is a lot more than a global variable in disguise. That's what makes it especially bad. It combines the global-ness (which is usually bad) with another concept which is *also* bad (that of not letting the programmer instantiate a class if he decides he needs an instance)They are often *used* as global variables, yes. And then they drag in the other nasty side effect as well, and cripple the codebase.
jalf
It should also be noted that singletons don't have to have public accessibility. A singleton can very well be internal to the library and never exposed to the user. So they're not necessarily "global" in that sense.
SnOrfus
+2  A: 

I think this is the most robust version for C#:

using System;
using System.Collections;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Same instance?
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 server requests
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // "Singleton"

  class LoadBalancer
  {
    private static LoadBalancer instance;
    private ArrayList servers = new ArrayList();

    private Random random = new Random();

    // Lock synchronization object
    private static object syncLock = new object();

    // Constructor (protected)
    protected LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      // Support multithreaded applications through
      // 'Double checked locking' pattern which (once
      // the instance exists) avoids locking each
      // time the method is invoked
      if (instance == null)
      {
        lock (syncLock)
        {
          if (instance == null)
          {
            instance = new LoadBalancer();
          }
        }
      }

      return instance;
    }

    // Simple, but effective random load balancer

    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

Here is the .NET-optimised version:

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Singleton.NETOptimized
{

  // MainApp test application

  class MainApp
  {

    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Confirm these are the same instance
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 requests for a server
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // Singleton

  sealed class LoadBalancer
  {
    // Static members are lazily initialized.
    // .NET guarantees thread safety for static initialization
    private static readonly LoadBalancer instance =
      new LoadBalancer();

    private ArrayList servers = new ArrayList();
    private Random random = new Random();

    // Note: constructor is private.
    private LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      return instance;
    }

    // Simple, but effective load balancer
    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

You can find this pattern at dotfactory.com.

artur02
You could strip out the parts that are not specifically relavent to Singletons to make the code easier to read.
Martin York
Also, your first version is not thread-safe because of possible read/write reordering. See http://stackoverflow.com/questions/9666/is-accessing-a-variable-in-c-an-atomic-operation#73827
Thomas Danecker
You'd have to make instance volatile to be thread-safe.
Thomas Danecker
+17  A: 

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.

DrPizza
Agreed. Two wrongs may make a right according to some, in the real world. But in programming, mixing two bad ideas does not result in a good one.
jalf
+1  A: 

Singletons are handy when you've got a lot code being run when you initialize and object. For example, when you using iBatis when you setup a persistence object it has to read all the configs, parse the maps, make sure its all correct, etc.. before getting to your code.

If you did this every time, performance would be much degraded. Using it in a singleton, you take that hit once and then all subsequent calls don't have to do it.

Brian
A: 

The real downfall of Singletons is that they break inheritance. You can't derive a new class to give you extended functionality unless you have access to the code where the Singleton is referenced. So, beyond the fact the the Singleton will make your code tightly coupled (fixable by a Strategy Pattern ... aka Dependency Injection) it will also prevent you from closing off sections of the code from revision (shared libraries).

So even the examples of loggers or thread pools are invalid and should be replaced by Strategies.

ZebZiggle
A: 

In desktop apps (I know, only us dinosaurs write these anymore!) they are essential for getting relatively unchanging global application settings - the user language, path to help files, user preferences etc which would otherwise have to propogate into every class and every dialog.

Edit - of course these should be read-only !

Martin Beckett
But this is begging the question; why do the user language and path to the help file have to be instances method _at all_?
DrPizza
We have globals for that. There's no need for making them singletons
jalf
Global variables - then how do you serialise them from registry/databse? Gobal class - then how do you ensure there is only one of them?
Martin Beckett
@mgb: you serialize them by reading values from registry/database and storing them in the global variables (this should probably be done at the top of your main function). you ensure there is only one object of a class, by creating only one object of class... really... is that hard to 'grep -rn "new \+global_class_name" .' ? really?
Paulius Maruška
@mgb: Why on Earth would I ensure there is only one? I just need to know that one instance always represents the *current* settings. but there's no reason why I shouldn't be allowed to have other settings objects around the place. Perhaps one for "the settings the user is currently defining, but has not yet applied", for example. Or one for "the configuration the user saved earlier so he can return to them later". Or one for each of your unit tests.
jalf
+11  A: 

I use Singletons as an interview test.

When I ask a developer to name some design patterns, if all they can name is Singleton, they're not hired.

Matt Cruikshank
Steve Yegge? Is that you?
1800 INFORMATION
Hard and fast rules about hiring will make you miss out on a wide diversity of potential employees.
Karl
A wide diversity of idiots exist. That doesn't mean they should be considered for hiring. If someone can mention no design patterns at all, I think they'd be preferable over someone who knows the singleton, and no other patterns.
jalf
For the record book - my response was tongue-in-cheek. In my actual interview process, I try to assess if we will need to tutor someone in C++, and how hard that will be. Some of my favorite candidates are people who DON'T know C++ inside-and-out, but I was able to have a great conversation with them about it.
Matt Cruikshank
Ha! That happened to me in an interview once.. I failed it... so many years ago
CVertex
Down vote. From my personal experience - programmer may not be able name any other patterns but Singleton, but that doesn't mean that he uses Singletons. Personally, I was using singletons in my code BEFORE I ever heard of them (I called them "smarter globals" - I knew what the global is). When I learned about them, when I learned about their pros and cons - I stopped using them. Suddenly, Unit testing became much more interesting to me when I stopped... Does that made me a worse programmer? Pfff...
Paulius Maruška
A: 

But when I need something like a Singleton, I often end up using a Schwarz Counter to instantiate it.

Matt Cruikshank
A: 

Singleton is a misconcept in OOP unless it's used as a misconcepted paradigm for application development.

:-)

Thevs
+2  A: 

Modern C++ Design by Alexandrescu has a thread-safe, inherietence-safe generic singleton.

For my 2p-worth, I think it's important to have defined lifetimes for your singletons (when it's absolutely necessary to use them). I normally don't let the static get() function instantiate anything, and leave set up and destruction to some dedicated section of the main app. This helps highlight dependencies between singletons but as stressed above it's best to just avoid them if possible.

tenpn
That book rules!
CVertex
+17  A: 

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 suppose to be a cache
  • In strings
  • In Sessions
  • I can go all day long

How to create the best singleton:

  • 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 (i.e. in Java every class definition is a singleton)
  • Provide a destructor or somehow figureout how to dispose resources
  • Use little memory
Javaxpert
wikipedia link: http://en.wikipedia.org/wiki/Cargo_cult_programming
alex
Actually, I think you are not quite correct either. I'd rephrase as:"If you *need* to have one and only one object of a type in system AND you *need* to have global access to it"Emphasis on need is mine - don't do it if its convenient, only if you MUST have it.
Dan
You're wrong too. If you need one and only one object, you create one and only one. If there is no logical way that two instances could ever be accomodated without irreversibly corrupting the application, you should consider making it a singleton. And then there's the other aspect, global access: If you don't need global access to the instance, it shouldn't be a singleton.
jalf
I thought I knew the singleton pattern from the Managed language world, but then I discovered Alexandrescu's book - "Modern C++ Design: Generic Programming and Design Patterns Applied". It changed everything. It goes into great detail about all these concerns with Singleton in C++, and the buddy OSS project, Loki is my first dependency into any C++ project I work on
CVertex
"Lazy or system initialization? Up to your requirements".... In a multi-threaded system, you have to work a bit harder to make lazy-initialisation thread-safe; it's probably not worth the effort.
Craig Young
+12  A: 

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:

  1. Global access to an object, and
  2. 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 world\n";

When you intended to write

std::cout << "hello world\n";

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 one, and there is no way creating two instances 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.

jalf
Assume, in a single thread, you need access to a specific Database object that is shared by an ORM class heirarchy, a ReportGenerator class, and a DataMaintenance class. While you could pass the database instance into the constructor of every object, this could make the instantiation list really long, and rather unmaintainable. Instead, you could create a SharedDatabase object as a singleton, and pass it around that way.
sheepsimulator
or you could make it a global, and get only *one* of the downsides of a singleton. With the singleton, you'd simultaneously limit yourself to one instance of that database cllass. Why do that? Or you could look at why you have so many dependencies that the instantiation list becomes "really long". Are they all necessary? Should some of them be delegated out to other components? Perhaps some of them could be packaged together in a struct so we can pass them around as a single argument. There are plenty of solutions, all of them better than singletons.
jalf
@ jalf - Here's the thing - Do you want multiple instances of a database object? Usually *no*, there is only one database. That is one instance where it is helpful to have a global entity that can only have a single instance.
sheepsimulator
I don't know. That's the key. I might at some point want another instance of the database class. Is it so hard to imagine that an application connects to more than one database? It doesn't seem so strange to me. But more importantly why paint yourself into a corner? If you suspect you only need one instance, then create one instance and make it global. It's not like you "accidentally" create new databases just because the constructor is public. So create one instance, make it global, and leave it at that. There's just no point in preventing me from creating another instance if I decide to.
jalf
Perhaps I didn't give a good example. One of my coworkers created a class called SpreaderController in a GUI program, that provided access to various internal spreader controller functions of a spreader controller device on a municipal snow plow truck. In any given snow plow truck, there is always, and guaranteed to only be, one spreader controller device. Also, many different places in this app need access to SpreaderController. The app also has many developers. To keep with the system model, and to prevent other developers from making multiple instances, he made it a Singleton.
sheepsimulator
Another example - telephone switch rack - Assume UK Robotics makes a telephone switch that has an administration unit, a box that governs all other telephone switching circuits in a rack. You really only want, programmatically, one AdministrationUnit class at any one time on a distributed code base through out a rack, and you don't want some silly developer out there making more than one. You could make it a global, and from an OO perspective this is a benefit, but in terms of engineering system design that is a fatal flaw - you won't have multiple administration units in the wild.
sheepsimulator
Yes, a singleton *might* be justified there. But I think you've just proven my point that it's only necessary in pretty exotic cases. Most software does not deal with snow plowing hardware.But I'm still not convinced. I agree that in your actual application you only want one of these. But what about your unit tests? Each of them should run in isolation, so they should ideally create their own SpreaderController - which is hard to do with a singleton.Finally, why would your coworkers create multiple instances in the first place? Is that a realistic scenario to protect against?
jalf
So your claim is that because we sometimes interface with physical devices of which only one exist, the singleton pattern is good *in general*? I stand by my claim. Usually, it is an awful idea. Sometimes, rarely, and working with external devices like snow plows is a good example, you really can only meaningfully have one instance. But those are special cases. I'd say a design pattern has to be applicable to more than snow plows to be considered "good".
jalf
And a point you missed is that while your last two examples arguably justify the "only one instance" limitation, they do nothing to justify the "globally accessible" one. Why on Earth should the entire codebase be able to acces your telephone switch's administration unit? The point in a singleton is to give you *both* traits. If you just need one or the other, you shouldn't use a singleton.
jalf
@ jalf - My goal was just to give you an example of where Singleton is useful in the wild, since you couldn't imagine any; I guess you don't see to many times to apply it your current line of work. I switched into snow plow programming from business applications solely because it would allow me to use Singleton. :) j/k I do agree with your premise that there are better ways to do these things, you've given me much to think about. Thanks for the discussion!
sheepsimulator
+1  A: 
  • How do you implement a Singleton correctly

There's one issue I've never seen mentioned, something I ran into at a previous job. We had C++ singletons that were shared between DLLs, and the usual mechanics of ensuring a single instance of a class just don't work. The problem is that each DLL gets its own set of static variables, along with the EXE. If your get_instance function is inline or part of a static library, each DLL will wind up with it's own copy of the "singleton".

The solution is to make sure the singleton code is only defined in one DLL or EXE, or create a singleton manager with those properties to parcel out instances.

Mark Ransom
+1  A: 

Most people use singletons when they are trying to make themselves feel good about using a global variable. There are legitimate uses, but most of the time when people use them, the fact that there can only be one instance is just a trivial fact compared to the fact that it's globally accessible.

Brad Barker
Agreed. That is why I asked the question. The uses cases for singelton are small.
Martin York
+1  A: 

Because a singleton only allows one instance to be created it effectively controls instance replication. for example you'd not need multiple instances of a lookup - a morse lookup map for example, thus wrapping it in a singleton class is apt. And just because you have a single instance of the class does not mean you are also limited on the number of references to that instance. You can queue calls(to avoid threading issues) to the instance and effect changes necessary. Yes, the general form of a singleton is a globally public one, you can certainly modify the design to create a more access restricted singleton. I haven't tired this before but I sure know it is possible. And to all those who commented saying the singleton pattern is utterly evil you should know this: yes it is evil if you do not use it properly or within it confines of effective functionality and predictable behavior: do not GENERALIZE.

gogole
A: 

As others have noted, major downsides to singletons include the inability to extend them, and losing the power to instantiate more than one instance, e.g. for testing purposes.

Some useful aspects of singletons:

1) lazy or upfront instantiation

2) handy for an object which requires setup and/or state

However, you don't have to use a singleton to get these benefits. You can write a normal object that does the work, and then have people access it via a factory (a separate object). The factory can worry about only instantiating one, and reusing it, etc., if need be. Also, if you program to an interface rather than a concrete class, the factory can use strategies, i.e. you can switch in and out various impls of the interface.

Finally, a factory lends itself to dependency injection technologies like spring etc.

lexh