We should all thank him for his contribution to our nation, hope he had peace and happyness in heaven.
Alex made a very good conclusion:
- Hides dependencies – A component that uses one or more singletons is hiding crucial information about your dependencies. It doesn’t take long for calls to a singleton to creep through your code base like kudzu, slowly attaching itself to every class in the system. Exposing that dependency forces you to think about it as you use a component. It also makes it more reusable as the caller can understand its requirements and how they might be satisfied.
- Hard to test – The hidden coupling of users on a singleton makes testing a nightmare as there is no way to mock out or inject a test instance of the singleton. Also, the state of the singleton affects the execution of a suite of tests such that they are not properly isolated from each other.
- Hard to subclass – Since initialization occurs in a singleton in static code, it is not amenable to subclassing because subclasses inherit the initialization code without the chance to override it.
- It’s a lie! (in most Java systems) – Singletons in Java are based on static variables, which are held per-classloader, not per-VM. In most systems of any complexity these days (any based on an app server, OSGi, Eclipse, plugins, etc) many classloaders will be involved. In that case, it is quite easy for two plugins to create their own instance of a singleton. Sometimes this is done by design and is desirable. But it’s also easy to screw up. It’s also usually critical that the singleton get created in the right classloader, which can make lazily constructing the singleton tricky.
- A singleton today is a multiple tomorrow – It’s not at all unusual to discover that you now need 2 or more of something you previously only needed one of. Hard-coding the singleton pattern into your code makes it impossible to satisfy that demand later. This probably seems really weird if it hasn’t happened to you, but it has happened more than once to me.
And the simplest solution to remove singleton, like Dong told me this afternoon, is to limit the use of instance on your own.
- Create an interface and a default implementation of your singleton
- Construct a single instance of your default implementation at the “top” of your system. This might be in a Spring config, or in code, or defined in a variety of ways depending on your system.
- Pass the single instance into each component that needs it (dependency injection)
The only problem of this approach is that we need to add some "top level" objects to our apps, and you might found these objects appear all over your code blocks to extreme.