Design patterns that I often avoid: Singleton

Learn the drawbacks of using the Singleton design pattern, one of the most widely used design patterns, and the alternatives to avoid its potential pitfalls

Drawbacks of the Singleton design pattern

Although design patterns are solutions to recurring problems and complexities in software designs, you should use design patterns only when they are needed. The Singleton design patter, for example, has several pitfalls that could discourage its use.

Typically, you would use the Singleton design pattern for implementing PrintSpoolers, Logging frameworks, etc. You would need just one instance of a logger throughout your application.

What is the Singleton design pattern and should I use it?

First off, let's understand what this pattern is all about. You use the Singleton design pattern to create classes of which only one instance can exist. In essence, the Singleton design pattern is a creational design pattern that can be used to implement a class of which one and only one instance can exist throughout the lifetime of your application. OK, 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 should be thread safe and static in nature. In using the Singleton pattern, you use a global instance and hide the dependencies. The dependencies are hidden inside your code and are not exposed through interfaces. As the application’s KLOC grows, this becomes increasingly difficult over time to inspect the code understand the dependencies and how the objects are related to each other. Also, providing a global access to an instance to avoid it being passed around in the application is considered a bad design practice -- an example of a code smell. You can actually get around the need of having to use the Singleton design pattern by using dependency injection in your applications.

Increases tight coupling

The Singleton design pattern promotes tight coupling between the classes in your application. Tight coupling increases the maintenance cost as maintenance and code refactoring becomes difficult. The reason is that changes to one component in your application is difficult as it would affect all other components that are connected to it. Note that Coupling is a term that is used to denote the degree of interdependence that exists between software modules and how closely they are connected to each other.

Unit tests become difficult

This increased coupling due to usage of the Singleton design pattern makes creating fakes during unit tests rather difficult. In other words, usage of the Singleton design pattern makes your life painful when writing unit tests since it becomes very difficult to identify the dependency chains so that the components in your application can be unit tested properly. Most importantly, you would need to use static methods when implementing the Singleton design pattern. Static methods make unit testing difficult since you cannot mock or stub. In essence, the types in your application that have dependency on a singleton class are relatively difficult to unit test. In unit testing, each of the unit tests should be independent of one another. Another reason due to which the Singleton design pattern makes your life difficult in unit testing is because they remain in memory till the application is alive. Hence they persist the state as long as the application remains in the memory.

Violates the Single Responsibility Principle

Another point to note here is that the Singleton design pattern violates the Single Responsibility Principle since the objects control how they are created and manage their life-cycle. This clearly contradicts the Single Responsibility Principle which states that a class should have one and only one reason for change. In order to limit the ability of creating instances of a class, a better alternative is in leveraging the factory or builder design patterns and then encapsulating the object creation logic. Another problem with the Singleton design pattern is that you can't extend them easily. You would want to take advantage of the Decorator design pattern to change the behavior.

Copyright © 2016 IDG Communications, Inc.

InfoWorld Technology of the Year Awards 2023. Now open for entries!