DEV Community

Cover image for Singleton Pattern in Kotlin: Challenges & Calling Strategies
Varun Singh
Varun Singh

Posted on • Edited on

Singleton Pattern in Kotlin: Challenges & Calling Strategies

The Singleton pattern is a foundational design pattern in Kotlin used to ensure a class has only one instance and provide global access to it. While Singleton offers benefits like centralized instance management, it also introduces complexities, particularly in calling scenarios. This article delves into the nuances of the Singleton pattern in Kotlin, discusses challenges it poses for testing, and provides practical solutions and strategies to overcome these challenges effectively.

Understanding the Singleton Pattern

The Singleton pattern restricts the instantiation of a class to one object, providing a global access point to that instance throughout the application's lifecycle. In Kotlin, it is typically implemented using a private constructor and a companion object.

Image description

Here, getInstance() ensures that only one instance of SingletonClass is created and returned whenever accessed.

Example Illustrating Testing Issues:

Consider the following example to illustrate calling challenges with Singleton:

Image description
Issues During Main call:

1.State Sharing:

In the first call (User 1), we added "Alice" to the repository.
In the second call (User 2), we added "Bob".
When we check the result of User 2, both "Alice" and "Bob" are in the list. This is because the Singleton instance is the same and maintains shared state.

2.Call is not isolated:

Ideally, each call should be isolated, meaning the result of one call should not affect another.
In this case, due to shared state (users list) between User 1 and User 2, the Calls are not isolated.

What could be the possible solution ?
Well their is a quick one..

Making use of resetInstance :)
Remember this function below -

Image description
Now we will use it in the main call to avoid state sharing and inturn use it in isolation.

Image description

By Using Manual Dependency Injection (DI):-

DI is a design pattern that enables the inversion of control, allowing dependencies to be injected into a class rather than the class creating them itself.

Image description

By defining an interface (SingletonRepository), the implementation (SingletonRepositoryImpl) is decoupled from its usage. This allows for different implementations to be used without changing the dependent code.

Check out the Dependency Injection frameworks like Dagger or Hilt to avoid Singleton pattern entirely

Dagger - [https://developer.android.com/training/dependency-injection/dagger-basics?authuser=1]
Dagger-Hilt-[https://developer.android.com/training/dependency-injection/hilt-android#component-hierarchy]

Hope you enjoyed my article. This is my first one. See you next time with more topics until then Tata!!

Top comments (0)