There are some things that people always talk about, they think they know everything about it. But this is actually an indication that something is wrong here. Why? Well, there are lots of ways (wrong ones) to implement Singleton that it raises a question. Is it really useful? How?
I am not going to talk here about if Singleton is a good pattern or not, or how to implement it. I like talking about more difficult ones. And Singleton is really simple. It just ensures that item will get initialized once and only once. How is it done, it depends on the programming language, compiler, even the context (clearly, it is impossible to have Singleton design pattern implementation on two separate devices :)), and lots of other things that can come by.
So, what is the problem actually that Singleton solves? It appears that no problem is being solved. Mostly, more problems ARE INTRODUCED than solved in this way. If you like, you can take a look into this example: https://sourcemaking.com/design_patterns/singleton . Example here is some government or government institution. It looks really “developer friendly” (oh, the irony). However, it is not really a Singleton, since governments can change and they change every term, so how unique is this example… Well, I am unable to comprehend this.
Another popular example for Singleton is logging something for some reason. But why people choose to use Singleton for loggers? I am not sure about that, either. Maybe it is the influence of bad examples for usage of Singleton. Clearly, you can create the logger in the following way (if not, please tell me why):
- Introduce ILogger (some interface required for logging).
- Introduce Logger that implements ILogger.
- Instantiate Logger during app startup or add it to IoC Container.
- Add ILogger as dependency everywhere it needs to be used.
However, it becomes a bit of problem when IoC Container is not used (or can not be used just right now), and there are lots of classes that needs logging. So, some people just introduce Logger as singleton. And yes, then it logs everything you want, but this introduces huge code smell that is hard to resolve. Also, it is not unit testable or in order to unit test it you are required to add some magical stuff that other developer who looks just into your unit tests might not know anything about it. And sometimes you might really want to test what actually gets logged. Thus, from my point of view Singleton mostly is used by people who are not tend to refactor their architecture of their software, and they try to use most short-sighted way of thinking. This is when Singleton gets used.
Still, Singleton CAN be useful sometimes. When? In IoC Containers it can be useful. For instance, most of the IoC Containers instantiate objects that are memory location agnostic (and it should be), but sometimes building the infrastructure for the whole app we would like a couple of classes to be non-memory agnostic. For instance, maybe we would like to log all of the activity to RAM first, and then initiate some background thread that would flush all of this data to some storage to make it more efficient. In order to be able to conserve some memory, we might actually want to have a Singleton. However, most of the modern IoC Containers support ability to make class instance as Singleton (e.g. Autofac in the C#), so even in this case you would not need to implement Singleton, since it is done for you already by other developers who suffered all of the implementation pain for you. So, why would you want to suffer again if your goal is to develop some industry level app instead of learning? I think that development of commercial apps and learning should not be coupled too much.
In other words, Singleton has its’ own uses, but all of the modern frameworks take care of that for you mostly, so actually there is no need to implement Singleton for you (unless you are going to implement some framework which is the case pretty rarely today). It is simple and really addictive pattern to use, but if you think you want to use Singleton, you should think about refactoring your code instead, since in this way you are making your code even worse than it is right now.