• Post Reply Bookmark Topic Watch Topic
  • New Topic

Singleton as a pattern  RSS feed

 
Jeremy Botha
Ranch Hand
Posts: 125
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, all.

First, a preamble. Yes, I've searched; No, this isn't a query on how to implement Singleton, it's the start of (What I hope) will be an education for me on why so many people seem to hate Singleton as a design pattern.

At my previous job, I helped maintain a large, monolithic application suite (lets call it Foo for reference sake) which had been developed almost entirely using static variables and methods which were (obviously) entirely thread-unsafe. To say that we could break the application by calling methods in the 'incorrect' order was an understatement.

I and several other developers have had exposure to what we'd like to think is rudimentary OO principles, and we had numerous fights with the original developer of Foo. This developer was a prima donna who flew into fits of rage whenver we didn't conform to the 'model' (The model being global static variables and methods).

Now, one of my friends who is still maintaining Foo is now engaged in a war with the prima donna over the use of Singletons. Now, I've used Singletons, and I like them. They're a simple way to provide access to things like configuration settings or system information (for example), especially in a standalone context where you don't necessarilly have JNDI or other application server niceties.

What I'm struggling to understand is why so many people automatically label Singletons as a 'bad design decision' - Most of the times I've seen them used they're serving minor application helper roles; they're not the central classes of applications. Wracking my mind a bit, I guess you could replace them in these instances with objects which perform an identical role, are instantiated in whatever class, read their config data, and are then passed to the calling class. This strikes me as somewhat of a roundabout way to approach the problem.

So, what am I missing? Thanks in advance for any input.
Jeremy
 
fred rosenberger
lowercase baba
Bartender
Posts: 12563
49
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am not an expert, but here's what i've picked up... there's not necesarrily anything wrong with a singleton - it's just that the choice to USE a singleton is almost always wrong.

a major portion of the time, after implementing the singleton pattern and having your code rely on it being a singleton, you'll find you really do need 2. or 5. or 12.

in other words, it's not that you need ONE AND ONLY ONE, you just need some finite number. sometimes this doesn't appear until years down the road, but when it does, you hate yourself.

a factory (or an abstract factory - not sure which would be better) is usually the right choice. even if you design your factory to only let you make one, that's usually the better choice, because you can then later change the factory to allow only 2, or only 5 or only 12.

i'm sure someone is gonna argue/disagree with me. and i'm not sure i can support this anymore than what i've said. it's just what i've picked up from people who i think are better designers than me.
[ July 03, 2006: Message edited by: fred rosenberger ]
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24217
38
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So many of my design decisions these days (and those of other folk) are based on testability. If a class C depends on some other object O that it obtains by a static reference (a public final member, calling a static method, etc) then it's impossible to test C independently of O. And since O is likely to perform some service like logging that requires an external resource, it's not just test independence that is impacted, but you take on a great burden of complexity when writing tests for the interaction between C and O.

If, on the other hand, you can build an O and give it to C, as you describe -- a process which all the cool kids are calling dependency injection these days -- then when you're testing C, it's trivial to provide a stub or "mock" implementation of O, isolating C from the real O and allowing independent testing.
 
Jeremy Botha
Ranch Hand
Posts: 125
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Assuming your Singleton is reasonably independant, though, where do the problems come in?

Bear in mind, I'm not advocating using Singletons for heavy lifting. I'm primarilly concerned with access to situations where you know you're never going to need more than one object. Not know as in 'I'm reasonably certain', but know as in 'there is no conceivable situation where I will need more than one of these'.

Typical places I'd be tempted to use a Singleton myself are
1) A configuration manager that reads in a configuration file and then publishes the properties to whatever application class needs them. Yes, I could create a new configuration object whenever I need it, but that seems unnecessary to me.

2) A central repository of modules loaded by my application. If I need to access the methods of one module from another, I'm tempted to make the manager class a Singleton, simply for ease of access. Admittedly, I could pass references of it down from the main application class to the constructors of classes that need it.

I can't think of any other times I'd personally use Singleton, though.

J
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, Fred, how many instances of your factory should there be?

Just teasing, I happen to agree. I find Singleton appropriate for caches. As the oringinal post suggested, configuration is a fine example of such a cache. With some effort you can make a Factory Method that returns some implementation of an interface, you can use dependency injection or whatever floats your boat so your singleton can be pluggable and testable. Your singleton can use composition and all the same tricks again.

By the way, users of the singleton don't need to know it's a singleton. If as Fred suggests it turns out that 5 is the right answer, you can tune your creation mechanism to some other number. I'll repeat an old story - I had a singleton from a single-threaded client application that someone ported into our server. It wasn't thread safe so we just changed the getInstance() method to always return a new one. Nobody had to know.

Caches and any other members on the singleton are really just disguised globals, though. Anybody who knows the cache key can get something out, modify it and put it back so any notion of information hiding is thrown out. (Static variables have many of the same issues.) Misuse of a global can quickly go to bad places.

BTW: Kudos on being offended by your master designer's choices. Robert Martin's Agile Software Development book will blow your mind with the great things good design can do for you. (Others recommend Martin Fowler's refactoring book, too, but I haven't had my hands on it yet.) You'll get such a giant brain you can convince your designer he's evil ... or you'll have to find a new job.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!