A Design Pattern Trivialized by Kotlin: Singleton

This article describes the widely used design pattern Singleton, and shows how it is trivialized in Kotlin – there is a simple way to implement this pattern correctly, and with less effort.

Sometimes we only allow one instance of a class in our program, and we would like this instance to be easily accessed. (e.g. a logging class, read more here.)

How can we ensure this?

The Singleton pattern, which restricts the instantiation of a class to one “single” instance, is the solution. It solves the problem by making the class itself responsible for two things:

To achieve these two points, a typical implementation (in Java) will need to:

if instance is null ->
    - create an instance using the private constructor
    - store the instance in a static field
    - and return it to the caller
else -> 
    - return the instance directly

This is called “late initialization”, as the instance is not initialized until it is needed.

Here are some nice examples in Java, implementing this pattern in both single- and multi- threaded scenarios. Note that in the multithreaded example, a technique called double-checked locking is used to prevent race conditions. Some people argue that double-check lock is not the recommended way and suggest other solutions, but nevertheless we need to do extra stuff to guarantee thread safety.

Java is sometimes regarded as a “verbose” language, while Kotlin is seen as a “more concise Java” in some cases. Here comes an example: the implementation of the Singleton pattern is made much easier in Kotlin. We simply need to use an object declaration (example taken from the Kotlin doc):

object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ...
    }

    val allDataProviders: Collection<DataProvider>
        get() = // ...
}

And the way to use it is straightforward:

DataProviderManager.registerDataProvider(...)

The cool thing about this language feature is that, besides simplicity, Kotlin also ensures thread safety out-of-the-box.

Note that singletons in Kotlin are initialized lazily.