Singleton pattern

Singleton pattern

Summary

Singleton is a creational pattern that ensures a class only has one instance and provides a global point of access to it.

singleton-comic-1-en.png

(Image by refactoring.guru)

Problems

There are times when your application only needs to use one instance of a class, such as thread pools, database connection, caches, logger… In those cases, if we were to instantiate more than one object, we’d face some problems like overuse of resources and inconsistent results. The Singleton pattern ensures a class only has one instance, and that instance is easily accessible.

Solution

Below is the structure of Singleton pattern:

structure-en.png

(Image by refactoring.guru)

A typical implementation of a Singleton looks like this:

public class Singleton {

   private static volatile Singleton instance = null;

   private Singleton() {
   }

   public static Singleton getInstance() {
       if (instance == null) {
           synchronized (Singleton.class) {
               if (instance == null) {
                   instance = new Singleton();
               }
           }
       }
       return instance;
   }

   // Other useful methods
   //...
}

The Singleton class only has a private constructor to ensure there is no more than one instance is created in the application's lifetime. The class then provides a global access point to the instance for the client to use. Every time the getInstance() method is called, it will return the same object.

In this example, we use a double-checked locking technique to deal with a multi-threading environment. We also optimize by using lazy initialization to delay the creation of the instance until the first time it is needed, avoiding using resources unnecessarily. This is extremely useful when you have an object that is expensive to create, and the program might not use it at all.

Criticism of Singleton pattern

Singleton is the simplest and arguably the most controversial pattern in the GoF book, some developers even consider it as an antipattern. The biggest problem with Singleton is that it is a global state in disguise. You can easily access the Singleton from anywhere in the system, which means some dependencies are hidden. The hidden dependencies make testing harder because there is no way to mock out or inject a test instance of the Singleton. Most of the time, it is better to expose all dependencies through the interfaces. That helps your code more comprehensible, as you can immediately know the relationship between objects.

Another problem with Singleton is the class restriction on initializing the new object. Some people argue that in the future, you may find out that you need 2 or more of something you previously only needed one of. Hard-coding the Singleton pattern into your code makes it impossible to satisfy that demand later. One of the suggestions is that you are able to control the number of objects created in your code-flow, instead of depending on the class itself. More specifically, you should construct a single instance of your class at the “top” of your system, and then pass it to each component that needs it. Doing that helps avoid accidentally creating another object because the object is always available for use.

Singleton might still be useful under some circumstances. For example, there are some dependencies that span across multiple classes and multiple layers. I think it is fine to use Singleton instead of applying the dependency injection, as they are going to be everywhere anyway. Of course, if you want to unit-testing your low-level class that depends on the Singleton, you should always pass the Singleton to your class through an interface, and replace it with a mock object when writing a unit test.

That said, the important thing to remember is that design patterns are just a recipe. When you understand the concept, you can use it depending on your perspective and your application’s requirements. From time to time you might find out the ideal solution, and it is never too late to refactor.

References

Singleton

Patterns I Hate #1: Singleton - Alex Miller

Singleton vs Dependency Injection