Although design patterns are solutions to common problems and complexities in software designs, you should only use design patterns when they are needed. The Singleton design pattern, for example, has several pitfalls that might discourage its use.
Typically, you would use the Singleton design pattern to implement PrintSpoolers, logging frameworks, etc. You would only need one instance of a logger in your application.
What is the Singleton Design Pattern and should I use it?
First, let’s understand what this model is all about. You use the Singleton design pattern to create classes that only one instance can exist. Essentially, the Singleton design pattern is a creative design pattern that can be used to implement a class of which one and only one instance can exist throughout the lifespan of your application. Okay, but what’s so bad about the Singleton design pattern?
Dependencies are hidden
One of the most important design considerations of the Singleton design pattern is that a Singleton class must be thread-safe and static in nature. By using the Singleton pattern, you use a global instance and hide dependencies. Dependencies are hidden in your code and are not exposed through interfaces. As the KLOC of the application increases, it becomes more and more difficult over time to inspect the code, understand dependencies, and know how objects relate to each other. Additionally, providing global access to an instance to prevent it from being passed into the application is considered bad design practice – an example of code odor. You can actually get around the need to have to use the Singleton design pattern by using dependency injection in your applications.
Increase tight coupling
The Singleton design pattern promotes tight coupling between classes in your application. Tight coupling increases maintenance cost as code maintenance and refactoring becomes difficult. The reason is that changes to one component in your application are difficult because they would affect all other components connected to it. Note that coupling is a term used to refer to the degree of interdependence that exists between software modules and how closely they relate to each other.
Unit testing is getting tough
This increased coupling due to the use of the Singleton design pattern makes it quite difficult to create fakes during unit testing. In other words, using the Singleton design pattern makes your life painful when writing unit tests because it becomes very difficult to identify dependency chains so that the components of your application can be unit tested. correctly. Most importantly, you will need to use static methods when implementing the Singleton design pattern. Static methods make unit testing difficult because you can’t mock or stub. In essence, the types in your application that depend on a singleton class are relatively difficult to test individually. In unit tests, each of the unit tests must be independent of each other. Another reason the Singleton design pattern makes your life in unit testing difficult is that they stay in memory until the app is active. Therefore, they persist state as long as the application remains in memory.
Violates the principle of single liability
Another point to note here is that the Singleton design pattern violates the principle of single responsibility since objects control how they are created and manage their lifecycle. This clearly contradicts the principle of single responsibility which states that a class should have one and only one reason to change. In order to limit the possibility of creating instances of a class, a better alternative is to take advantage of factory or constructor design patterns and then encapsulate the object creation logic. Another problem with the Singleton design pattern is that you can’t extend them easily. You would like to take advantage of the Decorator design pattern to change the behavior.