« Kotlin Singleton Design Pattern

Kotlin Singleton Design Pattern

We will go through the Java code example to better understand the logic of the singleton design pattern, and then we will talk about how we provide this structure in Kotlin.

It is a design pattern that takes 1 place in memory at any T moment and allows us to operate on the same object every time that we try to use it.

The most well-known examples used in the Android field are the Local DB(Room) instance or the Retrofit instance that we created to send requests to remote servers. The main reasons for using singletons in these examples are to keep track of the transactions that we perform on these instances, because if another instance occurs in memory, we may not be able to track the previous transactions.

In addition, Singleton objects are static, so in short, we say to the Garbage Collector, don’t touch this object, its memory control is entirely mine. Therefore, the Singleton design pattern is very suitable to be abused and become an anti-pattern due to its structure, because if we use this structure in unnecessary processes(such as moving or storing data), it can easily become an anti-pattern and cause a memory leak. This is the disadvantage of the singleton design pattern because we need to make memory management as simple as possible.

1class mySingleton {
2
3 //Field
4 private volatile static mySingleton mySingleton;
5
6 //Constructor
7 private mySingleton() {
8 }
9
10 //Static Method that creates our object.
11 public static synchronized mySingleton newInstance() {
12
13 if (mySingleton == null) {
14 mySingleton = new mySingleton();
15 }
16
17 return mySingleton;
18
19
20 }
21
22}

1-First, we make the constructor method private to prevent the object of our class created from the outside.

2-Then we write the newInstance method as a static method because we need to access this method before our class is in memory, so we need to write it as static.

3-we saw that synchronized and volatile keywords were also added. The reason why we use these keywords here is to prevent other threads from accessing the newInstance() function at the same time while working with a multi-thread and to lock our newInstance() method for milliseconds while processing with the thread. In other words, it allows a single thread to operate on that function. Likewise, the volatile keyword is added to the field to prevent more than one thread from accessing at the same time.

Now that we have examined our Java example in detail with all its steps, let’s look at how to create this structure on the Kotlin side.

1object Singleton{}

As you can see, it’s really easy to create a singleton structure in Kotlin. In fact, Kotlin takes care of all the work for us in the background and gives us a very easy use. For better understanding, let’s see the exact Java equivalent of our Kotlin code with “Show Kotlin Bytecode”.

singleton.png

Additionally, if you want to set up a singleton structure that requires synchronized and volatile keywords, you can do so using the companion object.

1class Singelton private constructor(context: Context) {
2
3 companion object {
4
5 @Volatile
6 private var INSTANCE: Singelton? = null
7
8 fun getInstance(context: Context): Singelton =
9 INSTANCE ?: synchronized(this) {
10 INSTANCE ?: Singelton(context).also { INSTANCE = it }
11 }
12
13 }
14
15}