Are Singletons really that bad?
Possible Duplicate:
What is so bad about Singletons?
It's understandable that many design patterns can in some cases be abused, and like mom always said: "Too much of a good thing isn't always good!"
I'm noticing that these days, I'm using Singletons a lot, and I'm worried that I might be abusing the design pattern myself, and running deeper and deeper into a bad-practice kind of habit.
We're developing a Flex application that has a quite a large hierarchical data structure kept in memory while the user works on it. The user can load, save, change and refresh the data on demand.
This data is centralized by means of a Singleton class, which aggregates a couple of ArrayCollections, Arrays, value objects and some other native member variables exposed via getters and setters.
To get a reference to our data from anywhere in the application, we do the whole Model.getInstance() method type of thing, that I'm sure everyone is familiar with. This ensures that we always get our hands on the same copy of data, since when we designed, we said that only once instance is allowed to exist during the application lifetime.
From this central data repository, it's then easy for us to for example, dispatch property changed events, and can have multiple UI components that reference the central data, update their displays to reflect the data changes that have occurred.
So far, this approach has been effective and proven very practical to our circumstances.
I'm finding however, that I'm a little overeager when creating new classes. Questions like should a class be a Singleton, or should it rather be managed some other way, like maybe using a factory for example, tend to sometimes become a bit difficult, with a bit of uncertainty.
Where do I draw the line with singletons? Is there a good guideline for deciding when to use Singletons and when to stay away from them.
Also, can anyone recommend a good book on design patterns?
The key thing to remember is that design patterns are just a tool to help you understand the abstract concepts. Once you have that understanding, restricting yourself specifically to a "recipe" from a book is pointless and hurts your ability to write the code most appropriate for your purpose.
That said, reading books like GoF will present you with more ways to think about problems so that when the time comes to implement something on your own, you'll have a wider set of perspectives to approach the problem from.
In your case, if using singleton makes sense in every case, then go right ahead. If it "sort of" fits and you have to implement it in some clunky way, then you need to come up with a new solution. Forcing a pattern that isn't perfect is somewhat like hammering a square peg in a round hole.
Given that you say "this approach has been effective and proven very practical to our circumstances," I think you're doing fine.
Here are some good books:
Gang of Four Book - the classic book for design patterns
Head First Design Patterns - I've heard this recommended by a few people as an alternative
Yes, singletons are bad. They are bad because all they do for you is combine two properties, each of which is bad about 95% of the time. (Which would mean that on average, singletons are bad 99.75% of the time ;))
A singleton, as defined by the GoF, is a data structure which:
The first is generally considered a bad thing. We don't like globals. The second is a bit more subtle, but generally, there are virtually no cases where this is a reasonable restriction to enforce.
Sometimes, it only makes sense to have one instance of an object. In which case you choose to create only one. You don't need a singleton to enforce it.
And usually, even when it "makes sense" to have only one instance, it turns out not to make sense after all. Sooner or later, you're going to need more than one logger. Or more than one database. Or you're going to have to recreate resources for each of your unit tests, which means we have to be able to create them at will. It is prematurely removing flexibility from our code, before we understand the consequences.
Singletons hide dependencies and increase coupling (every class can potentially depend on a singleton, which means the class can not be reused in other projects unless we also reuse all our singletons), and because these dependencies are not immediately visible (as function/constructor parameters), we don't notice them, and typically don't think about it when we create them. It's so easy to just pull in a singleton, it acts almost as a local variable and all, so we tend to use them a lot once they're there. And that makes them almost impossible to remove again. You end up, perhaps not with spaghetti code, but with spaghetti dependency graphs. And sooner or later, your runaway dependencies will mean that singletons start depending on each others, and then you get circular dependencies when one is attempted initialized.
They make it extremely hard to unit-test. (How do you test a function that calls functions on a singleton object? We don't want the actual singleton code to be exercised, but how do we prevent that?
Yes, singletons are bad.
Sometimes, you really want a global. Then use a global, not a singleton.
Sometimes, very very very rarely, you may have a situation where creating multiple instance of a class is an error, where it can not be done without causing errors. (About the only case I can think of, and even that is contrived, is if you're representing some hardware device. You only have one GPU, so if you're going to map it to an object in your code, it would make sense that only one instance can exist). But if you find yourself in such a situation (and again, for emphasis, a situation where multiple instances cause serious errors, not just a situation where "I can't think of any use cases for more than one instance"), then enforce that constraint, but do it without also making the object globally visible.
Each of these two properties can be useful, in rare cases. But I can't think of a single case where the combination of them would be a good thing.
Unfortunately, a lot of people have got the idea that "Singletons are OOP-compliant globals." No, they're not. They still suffer the same problems as globals, in addition to introducing some other, completely unrelated ones. There is absolutely no reason to prefer a singleton over a plain old global.
Software developers seem to be pretty evenly split into two camps, depending on whether they favor an idealistic coding style or a pragmatic one:
Personally, I favor the pragmatic approach. Sometimes it makes sense to break the rules, but only if you really understand what you are doing and are willing to accept the associated risks. If you can answer "yes" to the questions below regarding your specific use case, the singleton pattern can yield some practical benefits.
上一篇: 什么是控制反转
下一篇: 单身人士真的很糟糕吗?