Why is the Singleton so attractive? I’ll be the first to admit: I liked it too. No, scratch that – I loved the Singleton. It felt like an old friend from the moment I laid eyes on it. It was simple and beautiful.
I’ll tell you why: it’s because the Singleton pattern is a throwback to non-OO programming. It’s a lifeline for people who didn’t understand a single word that the Gang of Four were trying to say. I don’t know how it got in there in the first place — some political OOPSLA pressure, no doubt — but it doesn’t belong in there. It’s Evil…
Here’s the “short” summary…
a) I haven’t covered even a tenth of the issues. But I’ll name a few of them.
b) One is memory management; a Singleton is basically just a memory leak, if nobody is going to be using it for a while. But you have no idea when to deallocate it, because nobody’s going to call you and say “nobody’s going to be using you for a while!”
Besides, you can’t tell who has kept around references to your Singleton instance, since you were pretty blase about handing it out, weren’t you? (Note: Java’s weak references can help with this issue).
c) Speaking of memory leaks, what if your Singleton has a handle to some limited resource, like a database or file handle? I guess you get to keep that sucker open until your program ends. Thank God C++ programs never last longer than about 10 minutes before crashing, usually from running out of resources, or from trying to access a Singleton that someone freed.
d) Another issue is that the Singleton design is syntactically noisy; most languages don’t support it (well, Ruby does, sadly, but that was probably before Matz knew any better), so you have to stick in boilerplate code not only in the Singleton, but in everyone who uses it.
e) Then there’s the subclassing thing. It’s almost impossible to subclass a Singleton, and if you manage it, then you shouldn’t have been using a Singleton in the first place. You don’t even want to go there. I’ve walked roads that I dare not recount. Just pretend you can’t do it, and you’ll save yourself amazing amounts of pain.
f) static methods are as flexible as granite. Every time you use one, you’re casting part of your program in concrete. Just make sure you don’t have your foot jammed in there as you’re watching it harden. Someday you will be amazed that, by gosh, you really DO need another implementation of that dang PrintSpooler class, and it should have been an interface, a factory, and a set of implementation classes. D’oh!
Don’t suppose that’s all. There are many other problems. For instance, try adding multithreading in and see what happens. Well, I’ll tell you what happens: half the time, you get a Doubleton or a Tripleton, unless you’re a synchronization expert, and having a Tripleton is about as desirable as having three Balrogs show up at your tea party. And even if you’re a synchronization expert and get the double-check idiom right, you’ve still got one Balrog to deal with, and they’re no picnic.
But these problems all fade into insignificance compared to the Big One, which is that the Singleton “pattern” encourages you to forget everything you know about OO design, since OO is hard, and procedural is easy…