If you like a heated discussion, just pick a few developers and start a conversation about singletons. Sentiments and opinions about that particular design pattern are all over the place. For some it is pure evil, because it is global state. For others, it is divine because it is a pattern from the
bible GoF book.
It is a GoF pattern, so it has to be good, right?
Singleton is mentioned as one of the patterns in the book “Design Patterns – Elements of Reusable Object-Oriented Software” by a group of authors commonly known as the “Gang of Four”. For many people that means it has to be a good pattern and they should use it as often as they like, or even as often as possible.
This is a fallacy, because that book is twenty years old and things have changed and evolved since then. I have written about adhering to design patterns in an earlier post.
The GoF don’t think you should use it too often, either
There is an episode of the “SE-Radio” Podcast where Johannes Thönes interviews three of the GoF members about their book and the evolution of design patterns. Towards the end they also talk specifically about Singleton. You can see a transcript of that section here.
The bottom line is that singleton never was a very desirable pattern to have in the first place. It is a design shortcut and using it to justify global state is and has always been wrong.
That does not mean Singletons are evil
Having global state is problematic at best. It can make your whole application glued together so tightly that unit tests are close to impossible and you end up with a collection of long-running interdependent system tests.
Avoid global state whenever possible.
But that does not mean that the pattern itself is bad. It is a good pattern to encapsulate global state. So if you really have the need of global state, then by all means make it a singleton.
When you can’t avoid global state, use a singleton.
If you listen to the podcast, you will hear about dependency injection being an alternative to many uses of the creational patterns mentioned in the GoF book. The reason that the book itself does not mention dependency injection is simply because it is too old – the advent of DI came after the book was published.
An often seen general approach for dependency injection are “Inversion of Control Containers”. When constructing an object that needs a specific service that would otherwise be implemented as a singleton, the IoC container is queried for an instance of that service.
The definition of dependencies has to start somewhere, and passing the IoC container from main down and up all the tiers of a big application is usually not desirable. So to close the circle, many implementations of IoC containers are – you guess it – Singletons or other instances of global state.