單例模式

什么是單例模式

單例模式是應(yīng)用最廣的設(shè)計(jì)模式之一。

在很多時(shí)候秸讹,一個(gè)應(yīng)用程序?qū)τ谝粋€(gè)類(lèi)只需要一個(gè)全局的實(shí)例對(duì)象以供調(diào)用雅倒,創(chuàng)建多個(gè)對(duì)象會(huì)導(dǎo)致對(duì)系統(tǒng)資源的浪費(fèi)且沒(méi)有任何意義,單例模式就為此而生蔑匣。

單例模式的實(shí)現(xiàn)思路

應(yīng)確保這個(gè)類(lèi)只能有一個(gè)實(shí)例,且自行實(shí)例化向整個(gè)系統(tǒng)提供這個(gè)實(shí)例凿将。

為了能夠?qū)崿F(xiàn)上述思路价脾,我們可有想出下面的幾個(gè)點(diǎn)。

  • 為了確保調(diào)用者無(wú)法自行創(chuàng)建該類(lèi)的實(shí)例化對(duì)象彼棍,所以應(yīng)該將該類(lèi)的構(gòu)造方法用private修飾膳算。
  • 因?yàn)樵搶?duì)象無(wú)法通過(guò)new創(chuàng)建涕蜂,所以類(lèi)中應(yīng)有一個(gè)該類(lèi)的靜態(tài)實(shí)例化對(duì)象作為調(diào)用的返回值映琳。
  • 為了將上述的靜態(tài)實(shí)例化對(duì)象返回,應(yīng)有一個(gè)公開(kāi)的方法將該對(duì)象作為返回值返回萨西。

單例的各種實(shí)現(xiàn)方式

有了思路,我們來(lái)一起看一下實(shí)現(xiàn)方法葱跋。

懶漢式單例

所謂懶漢式源梭,顧名思義它比較“懶”,它在類(lèi)加載的時(shí)候并不會(huì)去實(shí)例化應(yīng)返回的單例對(duì)象废麻,而是當(dāng)調(diào)用時(shí)才去判空來(lái)判斷是否創(chuàng)建該對(duì)象然后才作為返回值返回。

public class Singleton {
    private static Singleton instance;
    private Singleton() {
    }

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

餓漢式單例

而餓漢式卻與上面的懶漢是不同油宜,它不管你是否調(diào)用怜姿,我在類(lèi)加載的時(shí)候就去創(chuàng)建這個(gè)對(duì)象,方法調(diào)用時(shí)直接返回粪薛。

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

以上提到的兩種并沒(méi)有考慮多線程的情況搏恤,再高并發(fā)的情況下湃交,仍有可能會(huì)出現(xiàn)創(chuàng)建多個(gè)對(duì)象的可能,懶漢式雖然在方法前加上synchronized 可以解決搞莺,但由于每次調(diào)用都需要去進(jìn)行同步,造成不必要的開(kāi)銷(xiāo)迈喉,所以這種方式不推薦使用。

DCL單例

全稱(chēng)是Doucle Check Lock,這種實(shí)現(xiàn)方式既能在需要時(shí)才初始化單例孩革,又能夠保證線程安全得运,但是由于java內(nèi)存模型的原因或在高并發(fā)情況下仍有可能會(huì)失敗,但是由于Android開(kāi)發(fā)過(guò)程中一般不會(huì)出現(xiàn)高并發(fā)的情況熔掺,所以仍是使用最多的一種單例模式。

public class Singleton {
    private static Singleton instance;
    private Singleton() {
    }

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

解釋一下這里為什么會(huì)用到雙重判空推沸,簡(jiǎn)單來(lái)說(shuō)就是由于JVM的原因券坞,如果你僅僅是單重判空,可能會(huì)發(fā)生這樣的情況:假設(shè)有兩個(gè)線程深浮,在第一個(gè)線程判空成功準(zhǔn)備去創(chuàng)建該對(duì)象的這個(gè)時(shí)候眠冈,可能另一個(gè)線程剛好完成了創(chuàng)建,這個(gè)時(shí)候就出現(xiàn)了問(wèn)題蜗顽,所以在這里我們采用這種寫(xiě)法,能有效的避免這種情況的發(fā)生忿等。

靜態(tài)內(nèi)部類(lèi)單例

public class Singleton {
    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }
}

由于靜態(tài)內(nèi)部類(lèi)是線程安全的崔挖,所以這種方式肯定是沒(méi)有任何問(wèn)題的。

枚舉單例

public enum Singleton {
    INSTANCE;
}

和上面的方式一樣薛匪,只不過(guò)用枚舉來(lái)實(shí)現(xiàn)脓鹃,因?yàn)槊杜e也默認(rèn)是線程安全的。只不過(guò)由于Android開(kāi)發(fā)中并不推薦使用枚舉類(lèi),所以很少看到岩齿。

單例模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 減少了內(nèi)存開(kāi)支(只能創(chuàng)建一個(gè)對(duì)象)苞俘。
  • 減少了性能開(kāi)銷(xiāo)(通過(guò)永駐內(nèi)存來(lái)解決對(duì)象的頻繁創(chuàng)建與銷(xiāo)毀)。
  • 避免對(duì)資源的重復(fù)占用(只有一個(gè)對(duì)象去對(duì)另一個(gè)對(duì)象進(jìn)行操作)襟诸。
  • 優(yōu)化了資源訪問(wèn)(可以全局訪問(wèn))基协。

缺點(diǎn)

  • 擴(kuò)展性差(單例模式一般沒(méi)有接口,所以擴(kuò)展性差澜驮,如果要擴(kuò)展,一般只能通過(guò)直接修改代碼的方式來(lái)擴(kuò)展)悍缠。
  • 如果單例對(duì)象持有Context耐量,容易引發(fā)內(nèi)存泄露,所以一般傳遞給單例對(duì)象的Context都是Application Context廊蜒。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末山叮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屁倔,更是在濱河造成了極大的恐慌,老刑警劉巖问麸,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞎饲,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)疟呐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)东且,“玉大人,你說(shuō)我怎么就攤上這事鲁冯∩椋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵跨扮,是天一觀的道長(zhǎng)验毡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)晶通,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任拔莱,我火速辦了婚禮隘竭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尊剔。我一直安慰自己菱皆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布京痢。 她就那樣靜靜地躺著篷店,像睡著了一般臭家。 火紅的嫁衣襯著肌膚如雪方淤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天你踩,我揣著相機(jī)與錄音讳苦,去河邊找鬼。 笑死鸳谜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的束莫。 我是一名探鬼主播草描,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼饿敲!你這毒婦竟也來(lái)了逛绵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤术浪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后硕蛹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陕赃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颁股。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豌蟋,死狀恐怖桑滩,靈堂內(nèi)的尸體忽然破棺而出允睹,到底是詐尸還是另有隱情,我是刑警寧澤缭受,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站韭畸,受9級(jí)特大地震影響蔓搞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喂分,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一蒲祈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梆掸,春花似錦、人聲如沸酸钦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拔恰。三九已至,卻和暖如春财岔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匠璧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魔眨,地道東北人酿雪。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像朋凉,于是被迫代替她去往敵國(guó)和親醋安。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杂彭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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