Kotlin和Java中的單例

我們先看單例模式的定義:?jiǎn)卫J皆贘ava中是最簡(jiǎn)單的一種設(shè)計(jì)模式野哭,一個(gè)類負(fù)責(zé)創(chuàng)建自身唯一的對(duì)象,該對(duì)象可以全局訪問(wèn)幻件,且外部不需要實(shí)例化拨黔。

有些朋友剛剛從Java切到Kotlin,語(yǔ)法上有些不習(xí)慣绰沥,創(chuàng)建單例的時(shí)候不知道怎么寫(xiě)篱蝇,下面我提供幾種方法。

一徽曲、餓漢式

Java:

public class SingletonObject{
    private static SingletonObject instance = new SingletonObject();
    
    private SingleObject(){}
    
    public static SingletonObject getInstance(){
        return instance;
    }

    public void something(){
        //do something
    }
}

Kotlin:

object SingletonObject{

    fun something(){
        //do something
    }    
}

一行代碼就可以實(shí)現(xiàn)零截,通過(guò)反編譯成java語(yǔ)言不難發(fā)現(xiàn)寫(xiě)法上都是一樣的

public final class SingletonObject {
   @NotNull
   public static final SingletonObject INSTANCE;

   public final void something() {
   }

   private SingletonObject() {
   }

   static {
      SingletonObject var0 = new SingletonObject();
      INSTANCE = var0;
   }
}

優(yōu)點(diǎn):最簡(jiǎn)單的一種方式,在類加載時(shí)就實(shí)例化秃臣,所以它是線程安全的涧衙,因?yàn)闆](méi)有鎖,不會(huì)影響訪問(wèn)效率奥此。
缺點(diǎn):在類加載時(shí)不管這個(gè)單例中的實(shí)例有沒(méi)有用到都被實(shí)例化了弧哎,在未被使用時(shí)會(huì)浪費(fèi)內(nèi)存。
總結(jié):類加載的原因雖然有很多稚虎,但單例類往往是因?yàn)檎{(diào)用了內(nèi)部的靜態(tài)函數(shù)撤嫩,所以一般情況下這種寫(xiě)法也能做到懶加載。我個(gè)人非常推薦這種寫(xiě)法蠢终,而且既然語(yǔ)言官方支持序攘,說(shuō)明這是在內(nèi)存和效率權(quán)衡下的最優(yōu)方案。

二寻拂、懶漢式

Java:

public class SingletonObject {
    private static SingletonObject instance;

    private SingletonObject() {
    }

    public static SingletonObject getInstance() {
        if (instance == null) {
            instance = new SingletonObject();
        }
        return instance;
    }

    public void something() {
        //do something
    }
}

Kotlin:

class SingletonObject private constructor(){

    fun something() {
        //do something
    }

    companion object {
        var instance: SingletonObject? = null
            get() {
                if (field == null) {
                    field = SingletonObject()
                }
                return field
            }
    }
}

優(yōu)點(diǎn):僅僅在使用時(shí)才會(huì)實(shí)例化這個(gè)單例程奠,減少了內(nèi)存占用。
缺點(diǎn):線程不安全兜喻,并且Kotlin的空安全特性會(huì)讓你用起來(lái)非常難受梦染,Koltin中每次訪問(wèn)這個(gè)單例都要處理空安全赡麦。
總結(jié):如果能確保沒(méi)有多線程訪問(wèn)朴皆,這種方法未嘗不可帕识。

三、加鎖懶漢式

總結(jié)了第二種方式的缺點(diǎn)遂铡,很容易想到可以在訪問(wèn)時(shí)加鎖解決問(wèn)題肮疗,加鎖懶漢式應(yīng)運(yùn)而生。
Java:

public class SingletonObject {
    private static SingletonObject instance;

    private SingletonObject() {
    }

    public static synchronized SingletonObject getInstance() {
        if (instance == null) {
            instance = new SingletonObject();
        }
        return instance;
    }

    public void something() {
        //do something
    }
}

Koltin:

class SingletonObject private constructor() {

    fun something() {
        //do something
    }

    companion object {

        var instance: SingletonObject? = null
            @Synchronized get() {
                if (field == null) {
                    field = SingletonObject()
                }
                return field
            }
    }
}

優(yōu)點(diǎn):僅僅在使用時(shí)才會(huì)實(shí)例化這個(gè)單例扒接,減少了內(nèi)存占用伪货,同時(shí)兼顧線程安全。
缺點(diǎn):每次訪問(wèn)這個(gè)單例都要同步鎖(效率低)钾怔、Koltin中要處理空安全碱呼。
總結(jié):如果獲取實(shí)例的次數(shù)很少,這種方法未嘗不可宗侦。

四愚臀、雙檢鎖懶漢式

既然知道了前兩種方案的缺點(diǎn),那有沒(méi)有完美方案呢矾利?有姑裂,雙檢鎖懶漢式就是
Java:

public class SingletonObject {
    private static SingletonObject instance;

    private SingletonObject() {
    }

    public static SingletonObject getInstance() {
        if (instance == null) {
            synchronized (SingletonObject.class) {
                if (instance == null) {
                    instance = new SingletonObject();
                }
            }
        }
        return instance;
    }

    public void something() {
        //do something
    }
}

Kotlin:

class SingletonObject private constructor() {

    fun something() {
        //do something
    }

    companion object {

        var instance: SingletonObject? = null
            get() {
                if (field == null) {
                    synchronized(SingletonObject::class.java) {
                        if (field == null) {
                            field = SingletonObject()
                        }
                    }
                }
                return field
            }
    }
}

優(yōu)點(diǎn):僅僅在使用時(shí)才會(huì)實(shí)例化這個(gè)單例,減少了內(nèi)存占用男旗,同時(shí)兼顧線程安全舶斧。
缺點(diǎn):寫(xiě)法較繁瑣、Koltin中要處理空安全察皇。
總結(jié):比較完美的方案茴厉,兼顧了效率和內(nèi)存,如果在Kotlin中什荣,那這不是最好的方案呀忧。

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

Java:

public class SingletonObject {

    private static class LazyHolder{
        private static SingletonObject instance = new SingletonObject();
    }

    private SingletonObject() {
    }

    public static SingletonObject getInstance() {
        return LazyHolder.instance;
    }

    public void something() {
        //do something
    }
}

Koltin:

class SingletonObject private constructor() {

    fun something() {
        //do something
    }

    val instance: SingletonObject
        get() = LazyHolder.singletonObject
    
    private object LazyHolder {
        val singletonObject = SingletonObject()
    }
}

對(duì)于這種實(shí)現(xiàn)方式溃睹,其實(shí)Kotlin還有另一種寫(xiě)法而账,通過(guò)lazy委托,寫(xiě)起來(lái)要簡(jiǎn)潔不少

class SingletonObject private constructor() {

    fun something() {
        //do something
    }

    val instance: SingletonObject by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
        SingletonObject()
    }
}

優(yōu)點(diǎn):僅僅在使用時(shí)才會(huì)實(shí)例化這個(gè)單例因篇,減少了內(nèi)存占用泞辐,同時(shí)兼顧線程安全。
總結(jié):算是第一種方法的補(bǔ)充版竞滓,通過(guò)可控類加載保證懶加載效果咐吼,沒(méi)有明顯的短板。不推薦的原因是會(huì)多寫(xiě)很多代碼商佑,Koltin調(diào)用時(shí)也不如第一種方式簡(jiǎn)單锯茄。

六、枚舉

Java:

enum SingletonObject {
    INSTANCE;

    public void something() {
        //do something
    }
}

Kotlin:

enum class SingletonObject {
    INSTANCE;

    fun something() {
        //do something
    }
}

優(yōu)點(diǎn):簡(jiǎn)單、線程安全肌幽,通過(guò)枚舉可以有效防止重復(fù)實(shí)例化晚碾,據(jù)說(shuō)還能防止反射。
總結(jié):比較冷門喂急,沒(méi)有明顯短板格嘁。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市廊移,隨后出現(xiàn)的幾起案子糕簿,更是在濱河造成了極大的恐慌,老刑警劉巖狡孔,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懂诗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苗膝,警方通過(guò)查閱死者的電腦和手機(jī)响禽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荚醒,“玉大人芋类,你說(shuō)我怎么就攤上這事〗绺螅” “怎么了侯繁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)泡躯。 經(jīng)常有香客問(wèn)我贮竟,道長(zhǎng),這世上最難降的妖魔是什么较剃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任咕别,我火速辦了婚禮,結(jié)果婚禮上写穴,老公的妹妹穿的比我還像新娘惰拱。我一直安慰自己,他們只是感情好啊送,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布偿短。 她就那樣靜靜地躺著,像睡著了一般馋没。 火紅的嫁衣襯著肌膚如雪昔逗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,246評(píng)論 1 308
  • 那天篷朵,我揣著相機(jī)與錄音勾怒,去河邊找鬼婆排。 笑死,一個(gè)胖子當(dāng)著我的面吹牛笔链,可吹牛的內(nèi)容都是我干的段只。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼卡乾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了缚够?” 一聲冷哼從身側(cè)響起幔妨,我...
    開(kāi)封第一講書(shū)人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谍椅,沒(méi)想到半個(gè)月后误堡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雏吭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年锁施,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杖们。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悉抵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出摘完,到底是詐尸還是另有隱情姥饰,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布孝治,位于F島的核電站列粪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谈飒。R本人自食惡果不足惜岂座,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杭措。 院中可真熱鬧费什,春花似錦、人聲如沸手素。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刑桑。三九已至氯质,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間祠斧,已是汗流浹背闻察。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辕漂。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓呢灶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親钉嘹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鸯乃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容