Вы находитесь на странице: 1из 2

Perils of the Singleton

By Matt Stephens
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 Single
tons 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 metho
d. 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 t
he problem - they can also lead to bad, inflexible designs.
Singletons are used inappropriately because people confuse having to make someth
ing 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 bei
ng:
Singletons make unit testing difficult. In particular, singletons tend t
o assume a lifetime longer than a single unit test; so they're difficult to rese
t ready for the next test.
They can't be reused. If you find that a different module can make use o
f 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 e
asily 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 h
ave a single instance, even if it doesn't need to. Changing cardinality could le
ad to all sorts of nasty bugs and breakage.
As you can see, Singletons restrict your design. By their very nature (and inten
t) 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 becom
e 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 aro
und the concept.
Change leads to breakage: but changing cardinality can lead to carnage. You'll f
ind that much of your code makes subtle assumptions based on the fact that certa
in classes have only one instance. In short, overuse of Singletons leads to slop
py 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 version
s 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 dis
cover that you can't, because the Singleton has locked you in. In short, avoidin
g 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 f
inding 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 whe
n 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 d
esign.
Singletons are problematic because they're so easy to create. This sounds counte
rintuitive, but it's an easy trap to fall into: they're a sloppy answer to a som
etimes tricky problem - how to associate multiple unrelated classes with a singl
e controller, without cluttering your interfaces by having to pass the controlle
r class around everywhere.
The simple answer is to do some class design up-front using paper and pen (or CA
SE tool or whatever), and work out in advance where all the dependencies are, an
d work out the least intrusive way of giving them access to the controller insta
nce - always remembering that what you are aiming for is a self contained contro
ller 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 c
lass 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 Single
ton: it's the right thing to do. But in all other cases, be wary of creating Sin
gletons for the sake of it, as they naturally restrict your design.

Вам также может понравиться