Perils of the Singleton
By
October 17, 2004
I realize this has been discussed in the past, but I thought I'd add my vote to the "Singletons are evil" debate. Not that Singletons really are evil, of course: not unless they're specifically programmed to do despicable things. And Singletons do have their uses. But the "evil", if that's the right word, is that they frequently are misused horribly.
A Singleton is a very simple design pattern which allows you to restrict a class to a single instance in an application. This is done by making the constructor private, and giving access to only a single instance via a static accessor method. Here's an example Singleton in Java:
public class BeanController {
private BeanController() {}
public static synchronized BeanController getInstance() {
if (instance == null) {
instance = new BeanController();
}
return instance;
}
private static BeanController instance = null;
}
As you can see, it's a very simple concept. So simple, in fact, that Singletons tend to be used almost everywhere. They're incredibly useful, but - and here's the problem - they can also lead to bad, inflexible designs.
Singletons are used inappropriately because people confuse having to make something single-instance with only happening to need a single instance at the time - two very different things.
There are several problems with the Singleton design pattern, the worst ones being:
 |
Singletons make unit testing difficult. In particular, singletons tend to assume a lifetime longer than a single unit test; so they're difficult to reset ready for the next test. |
 |
They can't be reused. If you find that a different module can make use of your controller class, you might be tempted to give it a separate instance to play around with. But you can't because it's a Singleton. But when you decide to change it, that leads to the next problem... |
 |
They're difficult to extend (assuming you want the subclass to also be a separate instance). Because the instance is got via a static method, it can't easily be overridden with a more specialized singleton. This can be worked around, but not particularly elegantly. |
 |
Any code which uses the class will naturally assume the class can only have a single instance, even if it doesn't need to. Changing cardinality could lead to all sorts of nasty bugs and breakage. |
As you can see, Singletons restrict your design. By their very nature (and intent) they lock you in to a single instance of a class. While this might be okay at the time, it restricts future refactoring of the design. Once a class has become a Singleton and other classes have begun using it, it can be difficult to make it a non-Singleton (multiton?), as the rest of the design will have evolved around the concept.
Change leads to breakage: but changing cardinality can lead to carnage. You'll find that much of your code makes subtle assumptions based on the fact that certain classes have only one instance. In short, overuse of Singletons leads to sloppy design.
If a class isn't restricted in this way, you can do all sorts of things with it: create unit tests more easily, create multiple versions, pass different versions around, clone them and so forth. You might not need to do any of these things at the time when you create the Singleton, but later you might need to - and discover that you can't, because the Singleton has locked you in. In short, avoiding Singletons wherever you can leads to a malleable, flexible design.
A common (mis)use of Singletons is to provide a static lookup - an easy way of finding a controller class from anywhere in the application: in other words, the OO equivalent of a global variable. While this can simplify your code nicely when used sparingly, a more appropriate solution would be to at least add a context parameter to the static lookup: so you get back a different instance depending on the context object that you pass in. Even if your application only ever uses the one context, it makes it that much easier to extend with new instances later. It's still not a complete solution, but gets you halfway to a more malleable design.
Singletons are problematic because they're so easy to create. This sounds counterintuitive, but it's an easy trap to fall into: they're a sloppy answer to a sometimes tricky problem - how to associate multiple unrelated classes with a single controller, without cluttering your interfaces by having to pass the controller class around everywhere.
The simple answer is to do some class design up-front using paper and pen (or CASE tool or whatever), and work out in advance where all the dependencies are, and work out the least intrusive way of giving them access to the controller instance - always remembering that what you are aiming for is a self contained controller class which can be created any number of times without causing errors.
It's worth emphasizing the point I made earlier: Much of the time, a Singleton class doesn't actually need to be restricted to a single instance: it only seems like it because (at the moment at least) the application doesn't need more than one instance of it. These are two very different things.
Singletons are not evil, although a genuine Singleton - a class which absolutely must be restricted to a single instance - is a rare thing. When you find such a class (e.g. a factory which churns out IDs), don't hesitate to make it a Singleton: it's the right thing to do. But in all other cases, be wary of creating Singletons for the sake of it, as they naturally restrict your design.
Elsewhere on the Web:
Singletons are Evil (Google search - a lot has already been written on the subject!)
Message Forum:
Please let us know what you think of this article...
Post a new message
Message Index: static method not required markn z3r0.00@gmail.com
re: static method not required Matt Stephens
Is that the real problem? piglet
The Messages: static method not required >> They're difficult to extend (assuming you want the subclass to also be a separate instance). Because the instance is got via a static method, it can't easily be overridden with a more specialized singleton. <<
Instead of using a static method to return the instance, you can do it via the Constructor.
markn z3r0.00@gmail.com Oz Mon Oct 18 02:53:32 BST 2004
re: static method not required Hi Mark,
That's the "workaround" I was alluding to; although it's generally accepted that that's how you extend singletons, it just feels like it's hacking the pattern to get around the problem. I'm sure others would disagree though! Matt Stephens London, England Mon Oct 18 11:35:15 BST 2004
Is that the real problem? I can't quite follow you here. The problem of changing cardinality should be relatively easy to solve: the getInstance() method can be adapted to different needs without breaking any client code. It can be seen more as a factory which may produce one ore several instances.
I worry much more about concurrency problems: synchronization, and the fact that a static variable as shown above isn't really a singleton (I think there's one instance per class loader). If I really depend on its being a singleton, I can't use the "singleton" pattern.
In mmy experience, in most cases where Singletons are used, the client doesn't care whether it's single or not, he only needs access to an instance and creating a new instance for each use seems like a waste of resources. The problem then is synchronization. Usually, what the client really needs isn't a synchronized singleton, it's one non synchronized instance per thread. But how to achieve this? piglet
Wed Oct 27 19:09:02 BST 2004
Post a new message
<< Back to Design
<< Back to Software Reality
|