Avoid to use the Singletons – if possible
Everybody knows the singleton pattern. If you want to allow in an app to use only one instance of an object you implement a static/class method which provides the instance for the caller and deny any other allocation. While there are situations where this is the only solution (1%) it seems the pattern is highly overused and better to avoid it this way.
This approach introduces more problems than solves.
- Classes depends on a particular class, not an interface (even if your method returns a reference to an interface you still have to use the class to access that method). If you want a code which is flexible and testable you have to remove all direct dependencies to classes but the singleton just introduces new ones.
- the singleton concept hurts the one class one concern rule: it has a functionality concern and also an object lifecycle concern.
- The singleton doesn’t have an owner, nobody manages its life-cycle. The singleton’s owner is itself. You cannot control when and how it can releases from memory and it won’t release until the program run.
- States: the singleton can have specific states but there are situations when you want to go back to the original state. With a regular object it’s quite simple, just release the old object and create a new. With a singleton you need some reset method and you have to be very careful: there is always something you forgot to set back to the original state. Moreover there can be living references to the singleton which thinks the reference still has the old state. This also causes problems.
- You can have more concurrent operations even if you want to have just one at a time. But if the singleton starts a background operation on another thread or got a callback later it causes several problems. It’s quite hard to maintain with a singleton while much simpler using simple objects
- It’s not necessarily impossible but harder to write a good unit test where you want to mock the singleton.
- Synchronization needed in a multi-threaded environment. You have to take care of the locking of the mutator methods.
How to replace the singleton
Passing an object as a parameter or setting a property is always clearer. It is the easiest way to mock and more readable for other developers. Dependency injection also a good solution against singleton. If you really need to access a global super object use a service locator/provider instead. It can be configured differently in the app and in the unit test and the different classes won’t directly depend on each other.
What’s the case with the real singletons
There can be situations where you really have to use a singleton (because you don’t have the source of the singleton etc). In this situations it’s better to create a simple proxy class (or a kind of service locator) which uses the singleton. This way you hide the original singleton class and can easily mock it in the test.