Kotlin中的單例模式有哪些

這篇文章給大家介紹Kotlin中的單例模式有哪些,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

創(chuàng)新互聯(lián)的客戶來自各行各業(yè),為了共同目標(biāo),我們在工作上密切配合,從創(chuàng)業(yè)型小企業(yè)到企事業(yè)單位,感謝他們對我們的要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。專業(yè)領(lǐng)域包括網(wǎng)站制作、做網(wǎng)站、電商網(wǎng)站開發(fā)、微信營銷、系統(tǒng)平臺開發(fā)。

一、餓漢式實現(xiàn)

//Java實現(xiàn)
public class SingletonDemo {
 private static SingletonDemo instance=new SingletonDemo();
 private SingletonDemo(){

 }
 public static SingletonDemo getInstance(){
 return instance;
 }
}
//Kotlin實現(xiàn)
object SingletonDemo

這里很多小伙伴,就吃了一驚。我靠一個object 關(guān)鍵字就完成相同的功能?一行代碼?

Kotlin的對象聲明

學(xué)習(xí)了Kotlin的小伙伴肯定知道,在Kotlin中類沒有靜態(tài)方法。如果你需要寫一個可以無需用一個類的實例來調(diào)用,但需要訪問類內(nèi)部的函數(shù)(例如,工廠方法,單例等),你可以把該類聲明為一個對象。該對象與其他語言的靜態(tài)成員是類似的。如果你想了解Kotlin對象聲明的更多內(nèi)容。請點擊- - - 傳送門

到這里,如果還是有很多小伙伴不是很相信一行代碼就能解決這個功能,我們可以通過一下方式查看Kotlin的字節(jié)碼。

查看Kotlin對應(yīng)字節(jié)碼

Kotlin中的單例模式有哪些

我們進(jìn)入我們的Android Studio(我的Android Studio 3.0,如果你的編譯器版本過低,請自動升級) 選擇Tools工具欄,選擇"Kotlin",選擇“Show Kotlin Bytecode"

選擇過后就會進(jìn)入到下方界面:

Kotlin中的單例模式有哪些

點擊"Decompile" 根據(jù)字節(jié)碼得到以下代碼

public final class SingletonDemo {
 public static final SingletonDemo INSTANCE;
 private SingletonDemo(){}
 static {
 SingletonDemo var0 = new SingletonDemo();
 INSTANCE = var0;
 }
}

通過以上代碼,我們了解事實就是這個樣子的,使用Kotlin"object"進(jìn)行對象聲明與我們的餓漢式單例的代碼是相同的。

二、懶漢式

//Java實現(xiàn)
public class SingletonDemo {
 private static SingletonDemo instance;
 private SingletonDemo(){}
 public static SingletonDemo getInstance(){
 if(instance==null){
  instance=new SingletonDemo();
 }
 return instance;
 }
}
//Kotlin實現(xiàn)
class SingletonDemo private constructor() {
 companion object {
 private var instance: SingletonDemo? = null
  get() {
  if (field == null) {
   field = SingletonDemo()
  }
  return field
  }
 fun get(): SingletonDemo{
 //細(xì)心的小伙伴肯定發(fā)現(xiàn)了,這里不用getInstance作為為方法名,是因為在伴生對象聲明時,內(nèi)部已有g(shù)etInstance方法,所以只能取其他名字
  return instance!!
 }
 }
}

上述代碼中,我們可以發(fā)現(xiàn)在Kotlin實現(xiàn)中,我們讓其主構(gòu)造函數(shù)私有化并自定義了其屬性訪問器,其余內(nèi)容大同小異。

如果有小伙伴不清楚Kotlin構(gòu)造函數(shù)的使用方式。請點擊 - - - 構(gòu)造函數(shù)
不清楚Kotlin的屬性與訪問器,請點擊 - - -屬性和字段

三、線程安全的懶漢式

//Java實現(xiàn)
public class SingletonDemo {
 private static SingletonDemo instance;
 private SingletonDemo(){}
 public static synchronized SingletonDemo getInstance(){//使用同步鎖
  if(instance==null){
   instance=new SingletonDemo();
  }
  return instance;
 }
}
//Kotlin實現(xiàn)
class SingletonDemo private constructor() {
 companion object {
  private var instance: SingletonDemo? = null
   get() {
    if (field == null) {
     field = SingletonDemo()
    }
    return field
   }
  @Synchronized
  fun get(): SingletonDemo{
   return instance!!
  }
 }
}

大家都知道在使用懶漢式會出現(xiàn)線程安全的問題,需要使用使用同步鎖,在Kotlin中,如果你需要將方法聲明為同步,需要添加**@Synchronized**注解。

四、雙重校驗鎖式(Double Check)

//Java實現(xiàn)
public class SingletonDemo {
 private volatile static SingletonDemo instance;
 private SingletonDemo(){} 
 public static SingletonDemo getInstance(){
  if(instance==null){
   synchronized (SingletonDemo.class){
    if(instance==null){
     instance=new SingletonDemo();
    }
   }
  }
  return instance;
 }
}
//kotlin實現(xiàn)
class SingletonDemo private constructor() {
 companion object {
  val instance: SingletonDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
  SingletonDemo() }
 }
}

哇!小伙伴們驚喜不,感不感動啊。我們居然幾行代碼就實現(xiàn)了多行的Java代碼。其中我們運用到了Kotlin的延遲屬性 Lazy。

Lazy是接受一個 lambda 并返回一個 Lazy 實例的函數(shù),返回的實例可以作為實現(xiàn)延遲屬性的委托: 第一次調(diào)用 get() 會執(zhí)行已傳遞給 lazy() 的 lambda 表達(dá)式并記錄結(jié)果, 后續(xù)調(diào)用 get() 只是返回記錄的結(jié)果。

這里還有有兩個額外的知識點。

  • 高階函數(shù),高階函數(shù)是將函數(shù)用作參數(shù)或返回值的函數(shù)(我很糾結(jié)我到底講不講,哎)。大家還是看這個 ---高階函數(shù)

  • 委托屬性

如果你了解以上知識點,我們直接來看Lazy的內(nèi)部實現(xiàn)。

Lazy內(nèi)部實現(xiàn)

public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
  when (mode) {
   LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
   LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
   LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
  }

觀察上述代碼,因為我們傳入的mode = LazyThreadSafetyMode.SYNCHRONIZED,
那么會直接走 SynchronizedLazyImpl,我們繼續(xù)觀察SynchronizedLazyImpl。

Lazy接口

SynchronizedLazyImpl實現(xiàn)了Lazy接口,Lazy具體接口如下:

public interface Lazy<out T> {
  //當(dāng)前實例化對象,一旦實例化后,該對象不會再改變
 public val value: T
 //返回true表示,已經(jīng)延遲實例化過了,false 表示,沒有被實例化,
 //一旦方法返回true,該方法會一直返回true,且不會再繼續(xù)實例化
 public fun isInitialized(): Boolean
}

繼續(xù)查看SynchronizedLazyImpl,具體實現(xiàn)如下:

SynchronizedLazyImpl內(nèi)部實現(xiàn)

private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
 private var initializer: (() -> T)? = initializer
 @Volatile private var _value: Any? = UNINITIALIZED_VALUE
 // final field is required to enable safe publication of constructed instance
 private val lock = lock ?: this

 override val value: T
  get() {
   val _v1 = _value
   //判斷是否已經(jīng)初始化過,如果初始化過直接返回,不在調(diào)用高級函數(shù)內(nèi)部邏輯
   if (_v1 !== UNINITIALIZED_VALUE) {
    @Suppress("UNCHECKED_CAST")
    return _v1 as T
   }

   return synchronized(lock) {
    val _v2 = _value
    if (_v2 !== UNINITIALIZED_VALUE) {
     @Suppress("UNCHECKED_CAST") (_v2 as T)
    }
    else {
     val typedValue = initializer!!()//調(diào)用高級函數(shù)獲取其返回值
     _value = typedValue //將返回值賦值給_value,用于下次判斷時,直接返回高級函數(shù)的返回值
     initializer = null
     typedValue 
    }
   }
  }
 //省略部分代碼
}

通過上述代碼,我們發(fā)現(xiàn) SynchronizedLazyImpl 覆蓋了Lazy接口的value屬性,并且重新了其屬性訪問器。其具體邏輯與Java的雙重檢驗是類似的。

到里這里其實大家還是肯定有疑問,我這里只是實例化了SynchronizedLazyImpl對象,并沒有進(jìn)行值的獲取,它是怎么拿到高階函數(shù)的返回值呢?。這里又涉及到了委托屬性。

委托屬性語法是: val/var <屬性名>: <類型> by <表達(dá)式>。在 by 后面的表達(dá)式是該 委托, 因為屬性對應(yīng)的 get()(和 set())會被委托給它的 getValue() 和 setValue() 方法。 屬性的委托不必實現(xiàn)任何的接口,但是需要提供一個 getValue() 函數(shù)(和 setValue()——對于 var 屬性)。

而Lazy.kt文件中,聲明了Lazy接口的getValue擴(kuò)展函數(shù)。故在最終賦值的時候會調(diào)用該方法。

@kotlin.internal.InlineOnly
//返回初始化的值。
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value

五、靜態(tài)內(nèi)部類式

//Java實現(xiàn)
public class SingletonDemo {
 private static class SingletonHolder{
  private static SingletonDemo instance=new SingletonDemo();
 }
 private SingletonDemo(){
  System.out.println("Singleton has loaded");
 }
 public static SingletonDemo getInstance(){
  return SingletonHolder.instance;
 }
}
//kotlin實現(xiàn)
class SingletonDemo private constructor() {
 companion object {
  val instance = SingletonHolder.holder
 }

 private object SingletonHolder {
  val holder= SingletonDemo()
 }
}

靜態(tài)內(nèi)部類的實現(xiàn)方式,也沒有什么好說的。Kotlin與Java實現(xiàn)基本雷同。

關(guān)于Kotlin中的單例模式有哪些就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

當(dāng)前標(biāo)題:Kotlin中的單例模式有哪些
分享URL:http://www.muchs.cn/article38/jpjgpp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、企業(yè)網(wǎng)站制作、網(wǎng)站營銷、ChatGPT、軟件開發(fā)響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)