Singleton pattern - arguments against it

Arguments against Singleton pattern

Some consider singleton to be an anti-pattern and a non-desirable coding practice because of two reasons.

  1. It introduces an application-level global state to the program. Any other object using the singleton has a direct dependency on it. That results in unnecessary inter-dependencies between classes and modules.
  2. The Singleton pattern also violates the single-responsibility principle, which states that “every class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class”. As singleton objects are responsible for at least two things:
    1. Ensuring only one instance is created
    2. Performing their normal operations

Singletons require special treatment in multi-threaded environments to ensure that separate threads don’t create multiple instances.

Singletons contradict the Dependency Injection principle and thus hinders testability. They make unit testing and mocking harder. As many mocking frameworks rely on inheritance, the private constructor makes singleton objects hard to mock. It essentially acts as a global constant, and it is hard to substitute it with a test double when needed.

Alternate approach

Using Spring’s singleton beans instead of implementing the singleton design pattern eliminates many of the above disadvantages.

Spring framework injects a bean in all classes that use it, but retains the flexibility to replace or extend it. The framework achieves that by maintaining control over the bean’s lifecycle. Therefore, it can later be replaced by another approach without any code having to change.

In addition, Spring beans make unit testing much simpler. Spring beans are easy to mock and the framework can inject them into test classes. We may choose to inject actual bean implementations or their mocks.

Note that singleton beans will not create only one instance of a class, but one bean per bean identifier in a container.


Links to this note