Adi said:
Someone else replied that [Singleton] is hard to test and make other
classes tightly coupled with this Singleton class. Somehow I doubt it
but I also can find any argument for that.
Singleton /can/ be a symptom of poor design. The worst thing about it (IMO) is
that people tend to focus on the idea that you /must/ only have one instance.
There is nothing wrong with /actually/ having only one instance, plus a
well-known way to find it; but for some weird reason people often go beyond
that and make it impossible to create other instances. That is restrictive,
unnecessary, and brittle.
Give you an example. Say we have some printer settings, and we'd like them to
be globally available. That's all fine so far -- a perfectly reasonable thing
to want to do. So we set up a class, PrinterSettings, and arrange that there
shall be a well-known instance (probably populated from the user's personal
preferences). We'll make that Singleton instance available from a static
method, PrinterSettings.getDefault(). That's still fine and dandy, and is
exactly the kind of thing that Singleton pattern is good for. But now, some
idiot decides to make it impossible to create /other/ instances of our
Singleton's class, that has all sorts of bad effects:
1) We probably can't risk modifying the Singleton instance, because it
might be in use by more than one thread. That was a problem with our original
design too, of course, and so we may (depending on the application) need a way
to avoid that problem. In our original design, the solution was simple -- just
make a copy of the PrinterSettings.getDefault() whenever we need a stable set
of settings. But with this new restriction we can't do that, so we have to
design some sort of complicated (and probably brittle) locking protocol to
allow us to "freeze" the settings while we are actually using them.
2) Nothing, /nothing/, has actually been gained by the restriction. The
software is not more flexible, more reliable, nor easier to understand. Its
just a bit of programmer fascism -- "Anything not mandatory is forbidden!".
Probably driven by insecurity.
3) Since we now have this single Singleton, programmers will be tempted to
write the code on the assumption that /everything/ will use that instance --
why pass it in a parameter when the called code can find the PrinterSettings
object directly by itself ? That leads to brittleness. If (or more likely,
when) the requirements change, e.g. to have two printers in the system, you
have to track down and eliminate all the code which /should/ have been
parameterised on the PrinterSettings to use, but which have hard-wired the
one-and-only-one Singleton assumption instead.
There may be situations where a one-and-only-one rule /is/ necessary -- but
they are very rare[*], and crop up far less often than legitimate needs for a
properly-written Singleton.
As to the "increased coupling" assertion. That's not really a problem of
Singleton as such, but of its typical expression using static methods -- all
static methods (and fields) lead to increased coupling (and so does direct us
of constructors, but that's another story...)
-- chris
[*] I can't think of any off the top of my head.