12/08/2018, 15:42

Singleton trong Kotlin

Hi, lâu lắm rồi mình mới lại lên viblo chém gió. Bình thường dùng java thì nó có static, thi thoảng thích thích với lười lười là quẳng luôn cho cái static. Nhưng từ cái đợt lâu lâu rồi nhảy sang code kotlin thì thấy nó lại không có static. Viết một class singleton thì không có static nên cũng bối ...

Hi, lâu lắm rồi mình mới lại lên viblo chém gió. Bình thường dùng java thì nó có static, thi thoảng thích thích với lười lười là quẳng luôn cho cái static. Nhưng từ cái đợt lâu lâu rồi nhảy sang code kotlin thì thấy nó lại không có static. Viết một class singleton thì không có static nên cũng bối rối chưa biết làm thế nào thì search mạng thấy nó ra cũng nhiều. Pick luôn một bài cùng chia sẻ với các bạn.

Kotlin không có thành phần static cho class, có nghĩa là bạn không thể tạo các static method, sẽ không có biến static trong class Kotlin của bạn. Vậy làm thế nào chúng ta có thể tạo singleton class trong Kotlin?

Thật may mắn, Kotlin object có thể xử lý vấn đề này. Cụ thể một class, từ khóa companion object sử dụng để member của nó có thể được access.

class MyClass { 
  companion object Factory {
    val info = "This is factory"    
    fun getMoreInfo():String { return "This is factory fun" }
  } 
}
MyClass.info             // This is factory
MyClass.getMoreInfo()    // This is factory fun

Tất cả các thuộc tính và method bên trong companion object đều có thể được gọi trực tiếp bằng cách sử dụng tên class kiểu như static. Và giờ chúng ta có thể tạo một class singleton dựa trên mẫu initialization-on-demand holder(https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom)

public class Singleton private constructor() {
    init { println("This ($this) is a singleton") }    

    private object Holder { val INSTANCE = Singleton() }

    companion object {
        val instance: Singleton by lazy { Holder.INSTANCE }
    }
    var b:String? = null
}

private constructor được sử dụng để chắc chắn rằng class không thể được initialized bất cứ đâu ngoại trừ bên trong bản thân nó. init sẽ được gọi khi class khởi tạo lần đầu tiên. Holder object & lazy instance được sử dụng để chắc chắn rằng chỉ có 1 instance của Singleton được tạo.

Cách dùng:

var first = Singleton.instance  // This (Singleton@7daf6ecc) is a
                                // singleton
first.b = "hello singleton"

var second = Singleton.instance
println(second.b)        // hello singleton

Đọc trên mạng thấy họ viết như vậy chứ mình chẳng bao giờ dùng lazy, toàn tương thẳng kiểu này vẫn sống ngon:

class Dog private constructor() {

    private var legs: Int = 0

    companion object {
        val instance = Dog()
    }

    init {
        legs = 4
    }

    fun getLegs(): Int {
        return legs
    }
}

Tham khảo: https://medium.com/@adinugroho/singleton-in-kotlin-502f80fd8a63

0