Singletons in Java

Started by
9 comments, last by M2tM 15 years, 2 months ago
Hello, I'm just starting to learn java and I've come across the singleton design pattern. After learning C++, I learned that Singletons=Bad (mostly due to threading, lack of flexibility, and to static initialization order fiasco). However, I'm curious as whether these reasons are valid in a Java context. I think the first two are relevant, but my professor is persistent that singletons are a perfectly valid design pattern (and she couldn't give me any reasons not to use it). She also said(directly quoting her): If you need to access a class from many different areas of a program and if you need exactly one copy of that instance, use the singleton design pattern. Any thoughts? I'm really disagreeing with her at the moment. Thanks, Mr Coolsman
Advertisement
No design pattern is inherently "bad". They are just misused and other approaches might be better. As has been said on here many times before there are two requirements that should be met if you want to use a singleton:

  • The object must be globally accessible

  • The object must not be instantiated more than once


Keep in mind the second rule is phrased the way it is because if you are using a singleton then it would be an ERROR to have more than one copy of this object. If you could theoretically have more than one copy of the object then it isn't an error, and thus shouldn't be a singleton.

However all the singleton-hate around here is mostly from a theoretical standpoint. While there are realistic design concerns about implementing singletons everywhere, there ARE situations where they are appropriate. This is something you have to decide, however.
Quote:Original post by MrCoolsman
However, I'm curious as whether these reasons are valid in a Java context.

Yes, singletons are still bad. If you insist on using singletons in Java, the recommended idiom involves an enum. The original design pattern (private constructor, lazy initialization, bla bla bla) is just too unsafe against attacks.

This is explained, amongst other things, in
>this great video @ 28:52 by Joshua Bloch.
You've covered two issues here. The first are implementation details -- whether or not a singleton implementation is usable in a multithreaded context, whether or not its allows for appropriate initialization, et cetera. These are less problematic; they are solvable within the context of a singleton most of the time.

The real issues are those you hinted at towards the end of your post. Your professor said "if you need to access a class from many different areas of a program and if you need exactly one copy of that instance, use the singleton design pattern," which is technically correct according to the Gamma, et al definition of the singleton. However, it implies the real, major problem: if you need to access a class from many different areas of a program. This is generally a bad design, regardless of language. Minimizing and factoring dependencies, and making them explicit and clear, is something you should strive for.

Furthermore, it is almost never the case that you need only one instance of an object. It is often the case that you want only one instance, in which case you can simply create only one rather than expend extra effort to build some contrived restriction into your code, thus making it less reusable. Singularity should be a property of the context in which an object is used, not of the object itself.

Here are some other arguments you may find interesting.
She sounds about right to me. Nobody will disagree that singleton should be used with caution, but few will say never to use it. Part of the reason it is bad is because it is almost too useful, I have caught myself trying using singletons to smooth over deeper problems with program design. This approach is only a temporary fix and will backfire eventually. I use singletons in my program for "state" classes, used to represent the behavior single state in a finite state machine. These classes are just methods so I don't ever need more than one, and so they get to be singletons.
The additional reason not to use Singleton in Java is that the execution model is so exotic and varied. Quick, under what circumstances does a singleton in a JSP page get instantiated?
Threading and the static initialisation order fiasco are implementation reasons to avoid Singletons in C++. By far the most important is the inflexibility. Code that makes use of Singletons is harder to maintain, to change, to reuse and to unit test.

Cases where you need "exactly one" are extremely rare. I honestly don't think I have come across such a type. Most of the time you only want one of something. Here is what most sane people would do: instantiate only one.

Singletons look seductive on paper and in small programs. An academic who may never have written a large program may never have encountered the issues. They scale badly.

The thing I hate *most* about Singletons is when people can't really admit what they really want to do: use a global. They write a load of boilerplate code to restrict instantiation when they could make a global. If you are going to use a quick-and-dirty design, be honest about it [grin]

Granted, in Java the main difference between a Singleton and a global is (from the client code) the visibility of the constructor.

IMHO. [smile]
Quote:She also said(directly quoting her): If you need to access a class from many different areas of a program and if you need exactly one copy of that instance, use the singleton design pattern.
This'll just be a reiteration of what's already been said, but I think it bears repeating...

First, there's a problem with how she states the second criterion. Needing only one instance is not a valid reason to use the singleton design pattern. It may seem right now like you'll only ever need one instance of X, but whatever X may be (a log file, a texture cache, etc.), you may very well find yourself wanting more than one in the future.

The second criterion should actually be, '...and if it would be an error for there to be more than one instance'. In other words, if you only need one instance right now, just create one instance; don't arbitrarily limit yourself by using a singleton.

The first criterion is also troublesome. Programmers are often poor judges of what actually 'needs' to be accessible from many different areas of the program. I don't know what your professor has in mind exactly, but on these forums at least we often see people using singletons for things that don't really need to be globally accessible (and that in fact it would be better not to make globally accessible).

If you feel comfortable doing so, you might ask your professor for an example of an object that would be a good candidate for the singleton pattern; the answer to that question will tell you a lot about the strength of her arguments (or lack thereof).
As has been said. Typically you hear examples crop up such as loggers and rendering as good singleton candidates and they can be better than most... But what if you want to instantiate a second logger instance for a test suite? What if you need a second window and therefore a second instance of your rendering classes? Why limit yourself? If you truly need global access there is a well-known construct to allow for it... A global.

That said, jyk has the skinny. In cases where it is an error to have more than one context and you -need- a global access point (not want) it is a good solution. These problems exist, but more typically either the global access point, the single instance, or both are simply wants rather than needs. In these cases it is best to re-evaluate what you are doing and approach it differently.

Certainly it isn't an error to use a singleton in cases where there is a valid need, but avoiding propagation of its instance retriever is a worthy cause. In cases where you require the global access point, use it. Otherwise creating a bridge from the interface and treating it as a normal object while keeping your singleton as localized as possible is safer and guarantees you will be able to remove the singleton quietly if you ever replace the method you are doing something. This may be overkill for a smaller project, but if you are working on a multi-man project of any scale it is ideal to go to certain lengths to avoid relying on them.
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Everything that needs to be said has really been said here -- but adding my own two cents on the "need only one" issue -- the word need, in this context, is a very precise interpretation of the word. Here, need must necessarily mean that it is a practical impossibility to implement the class in such a way as to allow more than one instance to co-exist -- That it is either a true and absolute impossibility due to factors outside your control, or that it would require so much engineering effort that the effort itself dwarfs the negative side effects of the pattern. Finding a real, justified use of a singleton is really a 1-in-a-million sort of thing. I can say this with all honesty -- I'd sooner believe the average applications programmer has won the state lottery than found a case where a singleton is necessary.

Now, all this is not to say that they don't get used, even in AAA code -- though they shouldn't. There's a reality that shortcuts are made in the real world, and with all the same real-world consequences that have been outlined above.

As long as you have the luxury of not having a boss breathing down your neck telling you to get it done yesterday you should take advantage of it, it'll make you a better coder.


Also, without challenging your instructors authority, I would be inclined to revisit the issue and bring up the points here, maybe even share a link to this thread with her before bringing it up in class. Have an honest discussion about it, share what you've learned here, show your classmates the other side of this coin, and rack up some of those "class involvement" points. Your classmates will thank you someday that you exposed them to the dark side of Singletons so early, even if it takes them some time to come around.

throw table_exception("(? ???)? ? ???");

This topic is closed to new replies.

Advertisement