Java Forum / General / December 2006
Singleton Pattern
Adi - 25 Nov 2006 05:23 GMT Dear all,
I have a question about singleton pattern. In my java user group, someone said that this pattern should be avoided, but he didn't explain the reason.
So I am curious here, is this statement true ?
Someone else replied that this pattern 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. What I know is just because this pattern is hard to test doesn't mean that this pattern should be avoided right ? I use this pattern a lot of times and found it useful.
Do you have any comments ?
Thanks,
saotome - 25 Nov 2006 05:44 GMT I personally use it plenty of times. I don't share your college's opinion. I don't understand why it would create tight coupling vs. a regular instantiation of an object.
> Dear all, > [quoted text clipped - 13 lines] > > Thanks, rxreyn3@gmail.com - 25 Nov 2006 06:28 GMT It's a matter of personal preference usually. The decision I make is on whether or not I can make static methods calls first. If I can't make static method to accompilsh what a class needs to do, yet I need to maintain a unique set of information, i'll create a singleton class.
Ryan
> Dear all, > [quoted text clipped - 13 lines] > > Thanks, Karl Uppiano - 25 Nov 2006 08:38 GMT > Dear all, > [quoted text clipped - 3 lines] > > So I am curious here, is this statement true ? Sometimes, I suppose.
> Someone else replied that this pattern is hard to test and make other > classes tightly coupled with this Singleton class. Somehow I doubt it [quoted text clipped - 3 lines] > > Do you have any comments ? If your design needs a singleton, then you should use a singleton. Perhaps your colleague was referring to some of the potential pitfalls (everything has pitfalls) described here: http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html
Mark Jeffcoat - 25 Nov 2006 10:08 GMT > Dear all, > > I have a question about singleton pattern. In my java user group, > someone said that this pattern should be avoided, but he didn't explain > the reason. There are a couple of really good reasons to avoid singletons:
First, because Singletons are Global Variables, returned from the grave where we tried to bury them so many years ago. They're very often used to pull in bits of extra state deep inside a program, jumping out without warning or any sort of control.
(Most common form: If your singleton has a name like "Configuration", you've got a cluster of global variables in a pretty wrapper.)
Second, because singletons are hard to test. To write useful unit tests, you have to know that the behavior of the code under test is the same as the behavior of the code in its final environment. Singletons allow you to not only make arbitrary changes in the environment, but they also introduce an order dependence into your tests. Every test that runs can change the state of your singleton, and that new state is carried over to the next test. Since this order probably is completely unrelated to the order in which the bits you're testing would be used in production, your tests are going to be much less likely to catch real problems--really, it's nearly impossible to guarantee that the behavior of code under test is not arbitrarily different than the same code in the production environment.
Third, using a singleton denies the possibility of certain extensions to your software. Someday, you're going to want two instances of whatever you were doing originally, and then many, and it's going to be annoying to have to run each instance in a separate JVM. This has actually happened to me, and I was, in fact, annoyed.
Reason 1 is enough: Globals are bad, because they will make your software hard to understand, and harder to maintain.
 Signature Mark Jeffcoat Austin, TX
Chris Uppal - 25 Nov 2006 11:56 GMT > First, because Singletons are Global Variables, returned from > the grave where we tried to bury them so many years ago. I often read this, but I don't think there's an ounce of truth in it.
More accurately, I think:
There is a need (a perfectly genuine need) to be able to put data in some "well-known" place where things can get at it. And without the data (or its location) needing to know about the users in advance (so the data is decoupled from its users, even though the users are coupled to the data -- but that's inevitable, it's part of the underlying logic, not an accident of poor design).
Global variables are one way of providing that. And when used for that purpose they work well. Of course, they can be misused to create "spaggetti data". But that doesn't mean that they are bad when used correctly.
One practical problem with global variables (considered as a technology intended to meet the requirement described above), is the name-clash thing. One solution to that is to use something like the Singleton pattern (or even just a public static field) in Java. That addresses exactly the same underlying need, but vastly reduces (not eliminates) the problem with unwanted name clashes. As you say, Singletons are essentially the same as global variable -- which is what you'd expect, they have been invented to address exactly the same need.
After all, what is a DBMS if it is not a chunk of (mutable) data available to all users at a well-known location ? Indeed it is available enterprise-wide, which puts poxy little Singleton classes in the shade ;-) Are DBMS's without problems ? Of course not, and some of those problems are exactly the same as the ones exhibited by other global varaiables (or Singletons) -- concurrent access, over-tight coupling, brittleness -- but I don't think many pundits would advocate scrapping the DBMS for those reasons.
There's nothing wrong with global data...
-- chris
Mark Jeffcoat - 28 Nov 2006 01:08 GMT >> First, because Singletons are Global Variables, returned from >> the grave where we tried to bury them so many years ago. > > I often read this, but I don't think there's an ounce of truth in it. I confess, I'm a little surprised. I thought I was making a claim on a similar level to "breathing is useful".
> More accurately, I think: > > There is a need (a perfectly genuine need) to be able to put data in some > "well-known" place where things can get at it. And without the data (or its > location) needing to know about the users in advance (so the data is decoupled > from its users, even though the users are coupled to the data -- but that's
> Global variables are one way of providing that. And when used for that purpose > they work well. Of course, they can be misused to create "spaggetti data". > But that doesn't mean that they are bad when used correctly. Okay. I certainly can't argue that it's possible to build a correct and clear program that used globals to store that data.
I see two potential problems:
First, it's not clear to me how I'm supposed to tell the difference between globals done right, and "spaghetti data". "Apply the intuition of an experienced programmer" probably works quite well for you, but it doesn't seem particularly helpful as advice to a novice. Would you care to take a stab at offering a few guidelines on how to recognize and avoid spaghetti data?
Second, I hate to lose the ability to analyze a method entirely in terms of its parameters and the its object's data (and thus have it easily testable). The way I solve the problem you lay out above while keeping that ability almost everywhere is to make sure that the classes that implement the business logic of the program only use that data in constructors and method calls; a method body never has access to the global data store (which might be, as you say, a DBMS).
 Signature Mark Jeffcoat Austin, TX
Karl Uppiano - 28 Nov 2006 01:32 GMT >>> First, because Singletons are Global Variables, returned from >>> the grave where we tried to bury them so many years ago. [quoted text clipped - 3 lines] > I confess, I'm a little surprised. I thought I was making > a claim on a similar level to "breathing is useful". I think globals exist because there is a legitimate use for them. Unfortunately, lazy programmers began to misuse them, and pretty soon everyone was saying "globals are bad, m'kay?". Now it's just politically incorrect to include them anywhere.
Any bad programming you can do with globals, you can do just as handily with instance member variables.
Chris Uppal - 28 Nov 2006 15:44 GMT > > > First, because Singletons are Global Variables, returned from > > > the grave where we tried to bury them so many years ago. [quoted text clipped - 3 lines] > I confess, I'm a little surprised. I thought I was making > a claim on a similar level to "breathing is useful". Yes, I understood that. Which is why I phrased my introductory remark rather more strongly than was actually justified ;-)
> First, it's not clear to me how I'm supposed to tell the > difference between globals done right, and "spaghetti data". [quoted text clipped - 3 lines] > at offering a few guidelines on how to recognize and avoid > spaghetti data? Can you give a reasonable summary of "functions done right" as opposed to "spaghetti code" ? I can't. The best I can do is offer some rules of thumb, and/or heuristics. Some, rather off the top of my head, and probably mutually contradictory (as is to be expected of heuristics).
Bad, or at least suspicious: Lots of globals (say, more than the number of major modules). A global which is used in only a few closely related places. A global with no obviously sensible (non-arbitrary) name. A global which changes its value even when the overall behaviour of the program doesn't change. A global used in modules which don't obviously need to know about it.
Good, or at least promising: A global corresponding to something in the underlying logical design, rather than a mere implementation artefact (e.g. something you could easily explain to a user). A global corresponding to something in the "ambient" (i.e. the execution environment of the whole program -- things like the OS, utility modules like Collections, and other stuff that a program can just assume). A global which removes the need for lots of duplicated code. A global which removes the need for pass-though parameterisation (Supplied by A to B, but not used by B except to pass it on to C).
Perhaps a more indirect guideline: Imagine that an experienced programmer/designer is looking at the application/library. S/he is familiar with the application domain, and with the functional requirements of the program, but has never seen any of the code. Now you tell them briefly about your global. Would they be able to guess with nearly perfect accuracy which parts of your code used it ? If so then you are probably on the right track.
"Global", of course, in the above is to be understood as anything which implements a global-like semantics, such as an application-wide registry, or use of the Singleton pattern, as well as actual global variables. Note that mutable static fields often count as global-like even if they are not used to implement a classical Singleton pattern.
> Second, I hate to lose the ability to analyze a method > entirely in terms of its parameters and the its object's [quoted text clipped - 5 lines] > has access to the global data store (which might be, as > you say, a DBMS). I think that's a good statement of where we disagree ;-) For me there's a design decision to be made: on one hand you can parameterise a module on <something> explicitly, on the other hand you can remove (or re-express) that parameterisation by representing the <something> as part of the ambient. In one case you end up passing the <something> around in parameters or as instance state; in the other case you use a global. There are advantages and disadvantages, both theoretical and practical, to both approaches. I admit that the former comes out on top much more often than the latter.
As an aside: I don't really buy the testing argument -- it seems to me that if the design of the application and/or the nature of the testing environment is such that global-like data makes unit testing difficult, then either the app or the testing environment is pretty deeply flawed. Fix whichever is broken, even if you /don't/ use globals.
-- chris
Mark Jeffcoat - 29 Nov 2006 21:52 GMT >> First, it's not clear to me how I'm supposed to tell the >> difference between globals done right, and "spaghetti data". [quoted text clipped - 8 lines] > and/or heuristics. Some, rather off the top of my head, and probably mutually > contradictory (as is to be expected of heuristics). Yeah. I was aware that I was asking a rather broad question; thanks for the effort you put into your answer.
> Bad, or at least suspicious: > Lots of globals (say, more than the number of major modules). [quoted text clipped - 3 lines] > doesn't change. > A global used in modules which don't obviously need to know about it. Unsurprisingly, I agree with everything on this list.
> Good, or at least promising: > A global corresponding to something in the underlying logical design, rather [quoted text clipped - 6 lines] > A global which removes the need for pass-though parameterisation (Supplied by A > to B, but not used by B except to pass it on to C). But some of these make me nervous. I'm kind of like pass-trhough parameterization; no surprises, and I know at a glance what objects are involved in the method. I do with Java had better (well, any) meta-syntax facilities, so you could replace a verbose and un-informative method delegation with a simple pointer to the class you're delegating too.
I've already proposed a different solution to the ambient environment that's conceptually quite similar; the biggest difference that I can see is that I'm proposing to explicitly pass the enviroment object around to anything that needs it.
A matter of taste, of course.
> "Global", of course, in the above is to be understood as anything which > implements a global-like semantics, such as an application-wide registry, or > use of the Singleton pattern, as well as actual global variables. Note that > mutable static fields often count as global-like even if they are not used to > implement a classical Singleton pattern. I'm actually largely okay with immutable static fields ... really, immutable anything that can be assigned a final value at compile time. Relaxing that restriction to assign-only-once fields at least is enough to completely avoid the spooky action at a distance problem, where the behavior of one part of the program changes when a not- obviously-related part makes a change to a shared value.
> As an aside: I don't really buy the testing argument -- it seems to me that if > the design of the application and/or the nature of the testing environment is > such that global-like data makes unit testing difficult, then either the app or > the testing environment is pretty deeply flawed. Fix whichever is broken, even > if you /don't/ use globals. In this context, when I say "testing", I'm talking about constructing unit tests, not discovering and fixing problems. I apologize for being unclear.
 Signature Mark Jeffcoat Austin, TX
Chris Uppal - 30 Nov 2006 13:15 GMT > I > do with Java had better (well, any) meta-syntax facilities, > so you could replace a verbose and un-informative method > delegation with a simple pointer to the class you're delegating > too. I don't suppose it would be particularly difficult to add-on something like that using the same kind(s) of bytecode manipulation technologies as the AOP folks. Scan for fields with an @Delegates annotation, decide (perhaps from further annotations) what "interfaces" to delegate to each, and inject some simple method definitions into the classfile -- nothing to it really ;-)
> I've already proposed a different solution to the > ambient environment that's conceptually quite similar; > the biggest difference that I can see is that I'm proposing > to explicitly pass the enviroment object around to anything > that needs it. I missed that somehow, and can't find it now. Can you post a link ?
Anyway, guessing what you mean from "I'm proposing to explicitly pass the environment object around to anything that needs it"; I think there's a fairly major problem with that. If you only pass the environment to objects/operations where it is actually needed, then you have an over-strong coupling (IMO) between the invoking code and the implementation code. You can easily remove that coupling by passing the environment object around unconditionally (and I've done that sort of thing before too); but then you have just reintroduced your globals, but in a different dress.
> > As an aside: I don't really buy the testing argument -- it seems to me > > that if the design of the application and/or the nature of the testing [quoted text clipped - 5 lines] > unit tests, not discovering and fixing problems. I apologize for being > unclear. I'm not sure whether you have misunderstood me -- it sounds as if you /might/ have -- but I also was talking about difficulty (or lack of it) in constructing unit tests (and other fine-granularity tests).
-- chris
RedGrittyBrick - 02 Dec 2006 12:08 GMT >>>> First, because Singletons are Global Variables, returned from >>>> the grave where we tried to bury them so many years ago. [quoted text clipped - 8 lines] >> First, it's not clear to me how I'm supposed to tell the >> difference between globals done right, and "spaghetti data". ... <snippage> ...
>> Would you care to take a stab >> at offering a few guidelines on how to recognize and avoid >> spaghetti data? <snip handy rules of thumb>
As someone relatively new to Java I can see the sense in what you are saying but I can't see how else to implement certain things.
I think I have three or more areas where I'm either using singletons, where singletons would be useful, or where I am doing something that I think is related (but I may be misunderstanding) Maybe someone could suggest best practice for some or all of these? ...
1) Constants that are used in several classes. In one case these are key values for user preferences that I am storing in a properties file. For example 'static String WINDOW_SIZE = "window_size";'. By using the constant, the compiler will pick up any typing errors, If I type 'prop.get("window-size");' I'll not get a compiler error, may not get a run-time error but will get unexpected behaviour. So in my class that contains my main() I define these as static constants. Elsewhere I use these constants as prop.get(MainClass.WINDOW_SIZE) etc. These are clearly global, I don't see a cleaner alternative.
2) Shared single resources. My example is a database connection. My app opens one connection, various classes use this to perform SQL transactions on unrelated tables etc. I could add a `connection` variable to every method call, but this makes for long strings of arguments to method calls, in some cases just so the variable can be passed on to other method calls (covered in Chris's rules of thumb). So I have a singleton to create the connection and it provides a public DBClass.getConnection() to return the connection. Obviously I have to be careful to avoid concurrent use of the connection. I don't know of a better way to share a single resource of this sort - is there one?
3) An "owner" for JDialogs. My App has a single frame. Many classes need to popup modal Dialogs or JOptionPanes, these need an owner to be specified. Currently I'm passing it as a parameter to the constructor of any class that needs it. I'm not entirely happy with this approach. The alternative seems to have a static variable MainClass.frame. Is there a better approach?
4) As an aside to the above, I sometimes need various classes to be able to things done by the main class, for example, update a status message at the bottom of the main window. To achieve this I pass a reference to the main JFrame in the constructor of classes created. So sometimes I have ...
class Mainform extends JFrame { Mainform() { ... FooClass f = new FooClass(this); BarClass b = new BarClass(this); ... } public void setStatus(String text) { ... } } class FooClass { JFrame parent; // *** Note "JFrame" *** FooClass(JFrame parent) { this.parent = parent; } xyzzy() { ... JOptionPane.showMessageDialog(parent, "Error" ...); ... } } class BarClass { Mainform parent; // *** Note "Mainform" *** BarClass() { this.parent = parent; } plugh() { ... parent.setStatus("Important thing accomplished"); ... JOptionPane.showMessageDialog(parent, ...); ... } } Having a Mainform variable in the constructor of BarClass means I can't re-use the BarClass in another application. I also have this JFrame/Mainform choice for parameter type that I find hard to resolve. Any suggestions?
Sorry for droning on, I hadn't intended to be this wordy :-) Feedback appreciated though.
andrewmcdonagh - 02 Dec 2006 18:30 GMT On Dec 2, 12:08 pm, RedGrittyBrick <RedGrittyBr...@SpamWeary.foo> wrote:
snipped...
> 2) Shared single resources. My example is a database connection. My app > opens one connection, various classes use this to perform SQL [quoted text clipped - 6 lines] > careful to avoid concurrent use of the connection. I don't know of a > better way to share a single resource of this sort - is there one? Noooo.......
Having a Singleton DB connection is the absolute worst use of the pattern - you don't need to enforce that there is only one connection, you simply need to store the (currently needed) single connection somewhere.
Choosing that usage, will cause you major problems when you need a second connection.
A better approach is for a singleton container which could return a number of connections based upon some form of ID.
connectionOne = Connections.getConnectionFor(db1); connectionTwo = Connections.getConnectionFor(db2);
RedGrittyBrick - 02 Dec 2006 19:02 GMT > On Dec 2, 12:08 pm, RedGrittyBrick <RedGrittyBr...@SpamWeary.foo> > wrote: [quoted text clipped - 27 lines] > connectionOne = Connections.getConnectionFor(db1); > connectionTwo = Connections.getConnectionFor(db2); Thanks Andrew, I'll ponder that.
Daniel Pitts - 03 Dec 2006 18:07 GMT [Snip previous discussion]
> As someone relatively new to Java I can see the sense in what you are > saying but I can't see how else to implement certain things. [quoted text clipped - 13 lines] > these constants as prop.get(MainClass.WINDOW_SIZE) etc. These are > clearly global, I don't see a cleaner alternative. Constants are not the same concept as singletons. Also, Java 1.5 supports enums, which are a better approach to those situations. I would use this to help qualify one case where a singleton is bad:
A singleton is a bad choice when you may ever want to dynamically change the behaviour of the object depending, such as by using polymorphism. Having a global String, or Integer object, does not fall under this category.
> 2) Shared single resources. My example is a database connection. My app > opens one connection, various classes use this to perform SQL [quoted text clipped - 6 lines] > careful to avoid concurrent use of the connection. I don't know of a > better way to share a single resource of this sort - is there one? Use the Dependency Injection pattern (a specific use of the Inversion of Control pattern). You're framework creates the single resource at the begining of executions (such as the main method), and the framework makes sure it gets where it needs to go (see springframework.org for a good IoC platform)
> 3) An "owner" for JDialogs. My App has a single frame. Many classes need > to popup modal Dialogs or JOptionPanes, these need an owner to be > specified. Currently I'm passing it as a parameter to the constructor of > any class that needs it. I'm not entirely happy with this approach. The > alternative seems to have a static variable MainClass.frame. Is there a > better approach? Singleton in this approach almost garuanties that you will never be able to extend your application to have more than a single frame. The best option here is to propagate the owner some how. Not necessarily in the constructor. If you have a reference to any component, you can retrieve its owning window from that.
> 4) As an aside to the above, I sometimes need various classes to be able > to things done by the main class, for example, update a status message [quoted text clipped - 39 lines] > JFrame/Mainform choice for parameter type that I find hard to resolve. > Any suggestions? Is it important to have parent be a "Mainform"? Could it just be a "JFrame"
Instead of using "Mainform.setStatus", consider having Mainform implement "StatusListener", and having any class that can change the status, do so with an event.
> Sorry for droning on, I hadn't intended to be this wordy :-) Feedback > appreciated though. I hope this helps. Feel free to break any part of this message apart and ask quesions on portions of it.
Good luck, Daniel.
Chris Uppal - 04 Dec 2006 15:41 GMT > 1) Constants that are used in several classes. Most people wouldn't see the use of such constants as problematic. The biggest source of problems from globals, singletons, or whatever, is that their values can change. If the value is intended to be constant (and /is/ constant ;-) then the problems are (at worst) much reduced.
> 2) Shared single resources. [...] I don't know of a > better way to share a single resource of this sort - is there one? In your particular example of database connections, you might want to consider what would happen if you changed your design to use a small pool of connections (e.g to make it easier to manage concurent use). The questions to ask yourself are: "am I likely to want to make that kind of change?", "does my current design make it hard to change that way?", and "is what I gain from my current design now enough to 'pay for' whatever pain we will incur /if/ we later want to change?". I.e. it's an engineering trade-off, and only you know what values to plug into the decision. FWIW, I think that most people, in most circumstances, would choose not to use a Singleton for this.
> 3) An "owner" for JDialogs. My App has a single frame. Many classes need > to popup modal Dialogs or JOptionPanes, these need an owner to be > specified. Currently I'm passing it as a parameter to the constructor of > any class that needs it. I'm not entirely happy with this approach. The > alternative seems to have a static variable MainClass.frame. Is there a > better approach? No idea, I'm afraid. (As an aside, I don't like GUIs which make use of popup dialogs, except very short-lived ones like file-selection dialogs.) At a guess, I'd suggest that if your code doesn't naturally have access to a suitable JFrame at the point where it discoveres that it needs to popup a dialog, then that might indicate that you are mixing presentation and domain logic too much.
> 4) As an aside to the above, I sometimes need various classes to be able > to things done by the main class, for example, update a status message > at the bottom of the main window. To achieve this I pass a reference to > the main JFrame in the constructor of classes created. Seems as if you are passing too much information to the other classes. They don't need to know about the whole JFrame/Mainform to display status text. If the "other classes" are GUI classes, then it seems that all they need is a refernce to, say, a JLabel which they update. If they are not GUI classes, then perhaps they should be updating some sort of StatusModel, or maybe triggering StatusChanged events which your GUI would observe.
The real problem here (as you understand, I think) is that the "other classes" are too tightly coupled to the main class(es). But using Singleton would not materially affect the degree of coupling -- the code would /look/ less coupled, but that would only be sweeping the problem under the mat. The two designs would still be connected together more than they should be, and when that happens it doesn't matter how you write the code (passing paramenters, using singletons, or whatever), the coupling is real, and won't go away.
-- chris
andrewmcdonagh - 02 Dec 2006 17:50 GMT On Nov 28, 3:44 pm, "Chris Uppal" <chris.up...@metagnostic.REMOVE-THIS.org> wrote:
> > > > First, becaus snipped...
> As an aside: I don't really buy the testing argument -- it seems to me that if > the design of the application and/or the nature of the testing environment is [quoted text clipped - 3 lines] > > -- chris Its not so much as they make it difficult, its that they make the tests brittle at best, or enforce an execution order of them at worst.
The usual way around these issues is to add some form of 'reset' mechanism to the Singleton, so that each unit test can 'reset' the state of the singleton before starting.
However, the better approach is to have the code under test, not know that the object is a Singleton, by passing it to the code, instead of the code using the static 'getInstance()' method.
If we then start passing around the Singleton instance to use, instead of using its static fetch method, then we should ask ourselves... "Why don't I just create one instance, instead of forcing a Singleton?"
Singletons (IMO) are best used as a global Container for various other objects. AKA a Toolbox.
In 10 years of development I've rarely found a real need for enforcing the 'must only be one' concept, that the Singleton is designed for. I have seen countless usages of Singleton, as a way of accessing from anywhere, a certain type of object, or values it holds.
Andrew
Chris Uppal - 04 Dec 2006 15:46 GMT > In 10 years of development I've rarely found a real need for enforcing > the 'must only be one' concept, that the Singleton is designed for. I > have seen countless usages of Singleton, as a way of accessing from > anywhere, a certain type of object, or values it holds. Which is almost exactly what I said myself (in the stuff that has been snipped). Singleton pattern is useful, when used judiciously, but whatever you do, don't get fooled into thinking you should enforce singularity.
Personally, I think the pattern is ill-named. "Distinguished Instance", or "Well-known Value", would be better, but you can't change the names of Patterns at will -- their names (however misleading) are the most valuable thing about them.
-- chris
Chris Thomasson - 25 Nov 2006 10:17 GMT > Dear all, > [quoted text clipped - 11 lines] > > Do you have any comments ? http://appcore.home.comcast.net/vzdoc/atomic/static-init/
http://groups.google.com/group/comp.programming.threads/browse_frm/thread/c7d417 e0b8aa516d
Chris Uppal - 25 Nov 2006 12:09 GMT > 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.
Lionel - 28 Nov 2006 01:26 GMT [snip]
> 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 [quoted text clipped - 5 lines] > idiot decides to make it impossible to create /other/ instances of our > Singleton's class, that has all sorts of bad effects: An interesting point you have made there. I had not considered this before.
I use Singleton in one of my programs. It acts as an interface to a database - no problems there. Originally it was a normal implementation of the Singleton pattern but I found that every time I wanted to use it I had to do the following:
SingletonClass singletonInstance = SingletonClass.getInstance(); singletonInstance.saveObject(objectInstance);
So I got sick of this and changed the methods to static methods to produce equivalent code:
SingletonClass.saveObject(objectInstance);
I can't possibly imagine where in my program it would ever be necessary to have an instance of this class, but I'm sure someone could think up something valid. So does that mean I should go back to the original design and add the additional annoying code everywhere?
Lionel.
Andreas Leitgeb - 28 Nov 2006 10:12 GMT > SingletonClass singletonInstance = SingletonClass.getInstance(); > singletonInstance.saveObject(objectInstance); ok, so just imagine that some day you want to extend SingletonClass to ExtSingletonClass, which overrides saveObject.
Doing it the "right" longish way, just means that you statically store an instance of the ExtSingletonClass and getInstance will return the derived object, and saveObject will be called from the derived object.
If instead you made saveObject a static method of SingletonClass, you'd have to modify all places where it's used.
Now, there is the obvious point of criticism: Why should one create an ExtSingletonClass, rather than just modifying the original SingletonClass? I can't give any real answer, except a dogmatic one: sometimes you just have to ... Sometimes, especially in the vicinity of Corba, the actual class implementing "SingletonClass" isn't even known at compile time, but specified per name at runtime.
So for your progs, you just ask yourself: Will this SingletonClass object ever need to be replaced with an object of a derived Class? If you can sufficiently safely answer "no" to that question, then go ahead and use static methods. The lesser typing might be worth the small risk of having made a wrong decision :-) Otherwise stick to getInstance() and non-static members.
Chris Uppal - 28 Nov 2006 15:04 GMT > SingletonClass singletonInstance = SingletonClass.getInstance(); > singletonInstance.saveObject(objectInstance); [quoted text clipped - 3 lines] > > SingletonClass.saveObject(objectInstance); I don't see anything much wrong with that. Or at least not inherently. I would hope that you've kept the old interface available for code which doesn't use the Single instance. So that the second form is just a short-cut for the former, rather than a redesign of the application to hard-wire the knowledge that there /cannot/ be another instance (the first form only hard-wires the knowledge that there is /a/ special instance, but not that there is only one).
-- chris
Lionel - 29 Nov 2006 03:10 GMT >> SingletonClass singletonInstance = SingletonClass.getInstance(); >> singletonInstance.saveObject(objectInstance); [quoted text clipped - 10 lines] > that there /cannot/ be another instance (the first form only hard-wires the > knowledge that there is /a/ special instance, but not that there is only one). Just a reply to acknowledge that I've read the two responses to my previous post and to say thanks :).
Lionel.
Arne Vajhøj - 25 Nov 2006 13:55 GMT > I have a question about singleton pattern. In my java user group, > someone said that this pattern should be avoided, but he didn't explain [quoted text clipped - 9 lines] > > Do you have any comments ? Singleton is a valid pattern.
Most of the criticism found on the net is ridiculous ("if you implement it wrong then it will not work" type).
The only real problem I can think of is a modifiable singleton in a clustered environment (or other multi JVM environment).
Arne
rxreyn3@gmail.com - 25 Nov 2006 18:33 GMT I'll be the first to admit that I have learned alot in this short discussion. Even if I don't agree.
Ryan
Arne Vajh?j wrote:
> > I have a question about singleton pattern. In my java user group, > > someone said that this pattern should be avoided, but he didn't explain [quoted text clipped - 19 lines] > > Arne andrewmcdonagh - 25 Nov 2006 20:20 GMT > > I have a question about singleton pattern. In my java user group, > > someone said that this pattern should be avoided, but he didn't explain [quoted text clipped - 17 lines] > > Arne The Singleton is a valid pattern.
The Singleton is the most used pattern.
The Singleton is the most abused pattern (e.g. used mainly for finding something at a well know location, rather than to enforce 'just one instance')
See: http://groups-beta.google.com/group/comp.object/browse_thread/thread/54abf37ca7b 7abda/0539f2454634cfca?lnk=st&q=Singleton+Pattern&rnum=5#0539f2454634cfca
The majority of times, having a global access to something is the usual reason for creating a Singleton. In these cases, its not a singleton that was required, but a singleton containing mutliple items - in other works a 'Container' or 'Toolbox'
Arne Vajhøj - 25 Nov 2006 21:45 GMT >>> I have a question about singleton pattern. In my java user group, >>> someone said that this pattern should be avoided, but he didn't explain [quoted text clipped - 11 lines] >> The only real problem I can think of is a modifiable singleton in a >> clustered environment (or other multi JVM environment).
> The Singleton is a valid pattern. > [quoted text clipped - 11 lines] > singleton that was required, but a singleton containing mutliple items > - in other works a 'Container' or 'Toolbox' As with most patterns there are a cases where it can be debated whether a specific pattern is the best solution or not.
Singleton is probably the most widely abused. But no surprise if it is the most widely used.
But from a practical point of view, then I would say that even in the cases where singleton is not the best solution, then it is usually not a bad solution either.
There are many much worse diseases than being over enthusiastic about singletons.
Arne
Karl Uppiano - 25 Nov 2006 22:58 GMT > As with most patterns there are a cases where it can be debated whether > a specific pattern is the best solution or not. [quoted text clipped - 8 lines] > There are many much worse diseases than being over enthusiastic > about singletons. I tend to agree. The question should not be "is the design pattern good or bad?" but rather, "does the solution require this design pattern?". A good design should attempt to choose a "good one" from the entire catalog of design patterns. All engineering is a trade-off, so there probably isn't a "best one", only one that doesn't suck too badly in any likely use-case.
Chris Uppal - 26 Nov 2006 15:27 GMT > I tend to agree. The question should not be "is the design pattern good or > bad?" but rather, "does the solution require this design pattern?". A good > design should attempt to choose a "good one" from the entire catalog of > design patterns. You may not have meant that exactly how it sounded, but if you do then I disagree profoundly. A good design is created on its own merits, /not/ by scanning some menu of available patterns.
-- chris
Arne Vajhøj - 26 Nov 2006 16:20 GMT >> I tend to agree. The question should not be "is the design pattern good or >> bad?" but rather, "does the solution require this design pattern?". A good [quoted text clipped - 4 lines] > disagree profoundly. A good design is created on its own merits, /not/ by > scanning some menu of available patterns. The difference between:
A) Create a good design based on your experience and knowledge including knowledge about established patterns.
B) At some point in the design process make a quick check on whether the problem matches an established pattern for design.
is not that big.
It is rather common to assume that if two solutions are technical equally good, then it is best to choose the most well known solution, because that makes the code more readable/maintainable.
Arne
Chris Uppal - 28 Nov 2006 15:16 GMT > A) Create a good design based on your experience and knowledge including > knowledge about established patterns. [quoted text clipped - 3 lines] > > is not that big. True. My objection is to the use of Patterns as if they were a menu of available design options. I would /hate/ to see a (would-be) designer saying (or thinking) something like "Blast! None of the Patterns fit this case -- I shall have to invent something". That is, to my mind, /exactly/ the wrong way around.
Of course, knowledge of existing working designs is vital imput to the design process -- but it's entirely irrelevant whether the community has developed an accepted Pattern Name for <some design that you've seen before>. (Which means I disagree with your last paragraph (not quoted)).
Put it this way: the idea I'm objecting to of what Patterns are for, and of how they are to be used, doesn't correspond to either (A) or (B).
-- chris
Arne Vajhøj - 07 Dec 2006 03:52 GMT >> A) Create a good design based on your experience and knowledge including >> knowledge about established patterns. [quoted text clipped - 9 lines] > shall have to invent something". That is, to my mind, /exactly/ the wrong way > around. I agree on that.
> Of course, knowledge of existing working designs is vital imput to the design > process -- but it's entirely irrelevant whether the community has developed an > accepted Pattern Name for <some design that you've seen before>. (Which means > I disagree with your last paragraph (not quoted)). Here it is: #It is rather common to assume that if two solutions are technical #equally good, then it is best to choose the most well known #solution, because that makes the code more readable/maintainable.
It does matter if it is a well known technique.
It simply makes maintenance easier if the programmer working on it recognize it.
It does not matter for the code whether it has a name or not, but it can make communication easier if it has a globally accepted name.
Arne
Chris Uppal - 08 Dec 2006 15:45 GMT [me:]
> > Of course, knowledge of existing working designs is vital imput to the > > design process -- but it's entirely irrelevant whether the community [quoted text clipped - 15 lines] > but it can make communication easier if it has a globally > accepted name. I'd put it that it is important for maintenance that the person working on the code understands[*] how it is structured (including any conventions which should be followed but are not actively enforced) and why it is structured that way. The way(s) to achieve that are well understood -- clear code, good comments (and any other documentation).
What established patterns give you is a short-cut towards good documentation -- a few words can establish an understanding of what the designer had in mind (including pointing out parallels with other system); leaving only the details to be filled in. So, patterns definitely help.
But I wouldn't choose a design just on the basis that it was less effort to document. Less effort for this reason, anyway. Designs which require less explanation are certainly much to be preferred over ones which require more -- but patterns don't (IMO) reduce the amount of explanation needed, they just streamline its expression.
-- chris
[*] Although one of the skills that a good maintenance programmer /may/ have is to work effectively without full understanding. I can't do it myself, but I have worked with people who can. I think they work by some sort of pattern-matching (not Pattern-matching ;-)
Karl Uppiano - 26 Nov 2006 19:41 GMT >> I tend to agree. The question should not be "is the design pattern good >> or [quoted text clipped - 6 lines] > disagree profoundly. A good design is created on its own merits, /not/ by > scanning some menu of available patterns. A good design is created on its own merits, but IME, a large application is usually built up from a judicious selection of standard components and design patterns: For loops, while loops, try/catch blocks, if/else blocks, switch statements, goto's, functional decomposition, object orientation, threads, critical sections, mutexes, semaphores, stacks, queues, arrays, lists, vectors, hash maps, singletons, resource adapters, enterprise service busses, and so on, every one a design pattern of some sort.
The actual design is application-specific of course, and its quality depends on the knowledge, ingenuity and creativity of the designer. However, in a modular, object-oriented world, re-use is encouraged. Therefore, I usually *do* scan some menu, in my mind, of available modules and design patterns, not always consciously of course -- starting with the JDK API or C++ object libraries, Google, -- looking for parts, to see if someone already invented what I need. That's the "research" part of R&D. In many cases, I will extend or modify what's available. If nothing is available, then I will create my own module from scratch as a last resort. Of course, the application-specific "glue" logic is usually not available off-the-shelf.
My particular coding style comes from the electronics industry, where I started my career. In electronics, everything is modular: Resistors, capacitors, inductors, transistors, integrated circuits... Sure, you could make your own components from scratch, but unless you're in that line of work, it is extremely time-consuming and fraught with difficulty. So, vendors build solutions from a menu of available parts and design patterns - e.g., most transistor audio amplifiers are based on the same tried and true design pattern, modified to meet specific requirements. But from these standard components and design patterns, I can build a cell phone, a wireless router, a television, microwave oven...
andrewmcdonagh - 25 Nov 2006 20:16 GMT > Dear all, > [quoted text clipped - 13 lines] > > Thanks, This has been discussed to death during the last 10 years......
Take a look at http://groups-beta.google.com/group/comp.object/browse_thread/thread/54abf37ca7b 7abda/0539f2454634cfca?lnk=st&q=Singleton+Pattern&rnum=5#0539f2454634cfca
for such a discussion.
Andrew
Adi - 25 Nov 2006 21:08 GMT > This has been discussed to death during the last 10 years...... > Take a look at http://groups-beta.google.com/group/comp.object/browse_thread/thread/54abf37ca7b 7abda/0539f2454634cfca?lnk=st&q=Singleton+Pattern&rnum=5#0539f2454634cfca
> for such a discussion. > Andrew Nice thread, thanks :)
Like ryan, I've learned a lot from here.
Daniel Pitts - 25 Nov 2006 21:13 GMT > Dear all, > [quoted text clipped - 13 lines] > > Thanks, The main reason is that it hinders Unit testing, but there are many other good arguments against singletons as well.
The alternative is often the use of Dependency Injection. This allows you to decouple the process of obtaining an object from the class altogether. A class which uses a Singleton will have to know exactly where to get it, and therefor coupling it to the Singleton. A class which utilizes Dependency Injection will know that it wants the "Singleton" object, but instead of asking for it directly, it will be given it by some outside source.
Lets give an analogy in psuedo-Java:
class Plant { double lightObsorbed = 0; void obsorbLight() { listObsorbed += LightSourceSingletonFactory.getLightSource().getLightInWatts(); } }
the Plant class is now coupled to LightSourceSingletonFactory and the LightSource interface. While it is not coupled to the implementation of LightSource.
class Plant { LightSource lightSource; void obsorbLight() { listObsorbed += lightSource.getLightInWatts(); }
void setLightSource(LightSource lightSource) { this.lightSource = lightSource; } }
Now, plant is no longer coupled to a singleton factory at all, and only the interface of LightSource. This would be useful of some day, your business logic needed to have both indoor plants (class LightBulb implements LightSource), and outdoor plants (class Sun implements LightSource).
It also allows you to have a unit test with a "mock" LightSource object.
Dependency Injection is a subcategory of Inversion of Control. The basis of the spring framework.
While the Singleton pattern DOES have uses, there are often other ways to achieve the same goal which lend themselves to a more flexible architecture. If you only need to ensure that there is only one instance of a particular class (eg. for a resource heavy object), you can still use DI and IoC, especially since the classes themselves don't do any form of object instansiation or retrieval.
It removes the burdon of object instantiation or retrieval from the business domain, and puts it into the framework.
Hope this helps, Daniel.
Nirav - 26 Nov 2006 08:46 GMT > Dear all, > [quoted text clipped - 13 lines] > > Thanks, I've few views of mine apart from the useful discussion here. Personally, I find singletons handy in most programming environments. My take on singleton is: never use them unless its inevitable (e.g. config registries and stateless utilities). Singleton implementations can easily become difficult to unit test, mock; which results in severe problems in large applications (and i hate spending time on instance recreation hacks, yuk). Most of the time I endup implementing minor testable variant of it, called monostate.
- Nirav Thaker
Ed - 28 Nov 2006 08:02 GMT Adi skrev:
> Dear all, > > I have a question about singleton pattern. > > Thanks, I won't add to the excellent debate on whether you should or should not use singletons, but it should be pointed out that there's a theorem called (oh, let's say) The Rationalisation Theorem which claims that any number of singletons within a given program can be reduced to one singleton without loss of ... well ... singletonness. (Interesting to note that this theorem wouldn't hold if the singleton didn't relate to both single instances and public access - a point for which it's often (and often correctly) maligned.)
Say you have two singletons: com.adi.model.ConcreteModelSingleton and com.adi.view.ConcreteViewSingleton
It's possible to tear an interface - ModelSingleton and ViewSingleton - from both and have them register their instances in a new singleton: com.adi.common.SystemSingleton
And then either remove the single-instance-guaranteeing machinery from the first two singletons themselves and put this in the SystemSingleton, or remove the public access modifier from the first two singletons (though this means having to instantiate them via some other public class in the same packages as the first two singletons) or both.
Either way, your first two singletons disappear and are replaced by the (then) only singleton in the system, which might look like:
public class SystemSingleton { SystemSingleton systemSingleton = new SystemSingleton(); ModelSingleton modelSingleton = null; private SystemSingleton(){}; public static SystemSingleton getInstance{ return systemSingleton; }
public void setModelSingleton(ModelSingleton modelSingleton) { this.modelSingleton = modelSingleton; }
public ModelSingleton getModelSingleton() { return modelSingleton; } }
Of course you have to guarantee a phased start-up, to ensure that the singletons register themselves before clients want to use them ...
.ed
-- www.EdmundKirwan.com - Home of The Fractal Class Composition.
Download Fractality, free Java code analyzer: www.EdmundKirwan.com/servlet/fractal/frac-page130.html
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|