【有夢(mèng)想的IT人】常用設(shè)計(jì)模式的總結(jié)(一) 單例模式

關(guān)于設(shè)計(jì)模式活合,我覺得是個(gè)程序員就應(yīng)該聽過白指,但是很多人用的時(shí)候還是一臉懵逼告嘲,今天26歲老司機(jī)總結(jié)一下我們常用的設(shè)計(jì)模式
設(shè)計(jì)模式一共有23種:

- 創(chuàng)建型(5種):主要用于處理對(duì)象的創(chuàng)建,實(shí)例化對(duì)象:
單例赋焕,建造者仰楚,原型,工廠方法蜜氨,抽象工廠

結(jié)構(gòu)型(7種):處理類或?qū)ο箝g的組合
適配器飒炎,裝飾者笆豁,結(jié)合,橋接煞赢,外觀照筑,享元凝危,代理

行為型(11種):描述類或?qū)ο笤鯓舆M(jìn)行交互和職責(zé)分配
策略,觀察者蛾默,迭代器支鸡,命令趁窃,備忘錄,中介者瀑构,解釋器检碗,訪問者,責(zé)任鏈折剃,狀態(tài),模板方法

今天我們主要研究一下單例模式:

單例模式(Singleton Pattern)

作用:保證 類在內(nèi)存中 的 對(duì)象唯一性边篮。

適用場(chǎng)景:

  • 1.避免創(chuàng)建多個(gè)實(shí)例浪費(fèi)資源

  • 2.避免多個(gè)實(shí)例因多次調(diào)用而出現(xiàn)錯(cuò)誤

  • 3.一般寫工具類奏甫,線程池阵子,緩存,數(shù)據(jù)庫會(huì)用到色乾。
    套路(三個(gè)要點(diǎn)):

  • 1.不允許在類外new對(duì)象 —— 構(gòu)造方法私有化

  • 2.在類中創(chuàng)建對(duì)象 —— 通過new在本類中創(chuàng)建一個(gè)實(shí)例

  • 3.對(duì)外提供獲取該實(shí)例的方法 —— 定義公有方法返回創(chuàng)建的實(shí)例
    餓漢與懶漢的區(qū)別

前者在類裝載時(shí)就實(shí)例化暖璧,后者只有在第一次被使用時(shí)才實(shí)例化澎办。
(餓漢的優(yōu)點(diǎn)是避免線程同步問題金砍,缺點(diǎn)是即使沒用到這個(gè)實(shí)例還是會(huì)加載)
(懶漢的優(yōu)點(diǎn)是實(shí)現(xiàn)了懶加載,但需要解決線程安全問題至会!)

5種常用單例套路:

1)餓漢式,沒有實(shí)現(xiàn)懶加載~

public class Singleton() {
    private static Singleton instance = new Singleton();
    private Singleton(){ }
    public static Singleton getInstance() { 
        return instance;  
    }
}
//獲取單例對(duì)象
Singleton mSingleton = Singleton.getInstance();

2)懶漢式
雖然達(dá)到了懶加載昆著,但是卻存在線程安全問題术陶,比如有兩個(gè)線程都
剛好執(zhí)行完if(instance == null)梧宫,接著準(zhǔn)備執(zhí)行instance = new Singleton()
語句,這樣的結(jié)果會(huì)導(dǎo)致我們實(shí)例化了兩個(gè)Singleton對(duì)象脓豪,
為了解決線程不安全問題扫夜,可以對(duì)getInstance()方法加鎖。

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

3)懶漢式加鎖版
首先普及synchronized當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí)堕阔,一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行超陆。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊时呀。

為getInstance方法加鎖雖然保證了線程安全捐韩,但是每次執(zhí)行g(shù)etInstance()
都需要同步,而實(shí)例化對(duì)象只需要執(zhí)行一次就夠了瞧预,后面獲取該示例垢油,
應(yīng)該直接return就好了,方法同步效率太低滩愁,一種改進(jìn)后的寫法是:
synchronized (Singleton.class) { instance = new Singleton(); }
但是硝枉,這樣寫依然是線程不安全的妻味,如果你還是想用懶漢式的話责球,推薦
雙重檢查鎖定(DCL雏逾,Double Check Lock)。

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

4)懶漢式雙重校驗(yàn)鎖(DCL)
首先普及Volatile:Volatile修飾的成員變量在每次被線程訪問時(shí)屑宠,都強(qiáng)迫從共享內(nèi)存中重讀該成員變量的值侨把。而且秋柄,當(dāng)成員變量發(fā)生變化時(shí)骇笔,強(qiáng)迫線程將變化值回寫到共享內(nèi)存笨触。這樣在任何時(shí)刻芦劣,兩個(gè)不同的線程總是看到某個(gè)成員變量的同一個(gè)值。

代碼中進(jìn)行了兩次if檢查说榆,這樣就可以保證線程安全虚吟,初始化一次后,
后面再次訪問時(shí)签财,if檢查串慰,直接return 實(shí)例化對(duì)象。volatile是1.5后
引入的唱蒸,volatile關(guān)鍵字會(huì)屏蔽Java虛擬機(jī)所做的一些代碼優(yōu)化邦鲫,會(huì)導(dǎo)
致系統(tǒng)運(yùn)行效率降低,而更好的寫法是使用靜態(tài)內(nèi)部類來實(shí)現(xiàn)單例神汹!

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

5)靜態(tài)內(nèi)部類實(shí)現(xiàn)單例(推薦)

和餓漢式類似庆捺,都是通過類加載機(jī)制來保證初始化實(shí)例的
時(shí)候只有一個(gè)線程,從而避免線程安全問題屁魏,餓漢式的
Singleton類被加載時(shí)疼燥,就會(huì)實(shí)例化披诗,而靜態(tài)內(nèi)部類這種剥槐,
當(dāng)Singleton類被加載時(shí),不會(huì)立即實(shí)例化蕊苗,調(diào)用getInstance()
方法才會(huì)裝載SingletonHolder類喉刘,從而完成Singleton的實(shí)例化造锅。

public class Singleton {
    private Singleton() { }
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton()
    }
}

結(jié)論:由以上結(jié)果可以得知單例模式為一個(gè)面向?qū)ο蟮膽?yīng)用程序提供了對(duì)象惟一的訪問點(diǎn)肺素,不管它實(shí)現(xiàn)何種功能,整個(gè)應(yīng)用程序都會(huì)同享一個(gè)實(shí)例對(duì)象塌西。

對(duì)于單例模式的幾種實(shí)現(xiàn)方式筹淫,知道餓漢式和懶漢式的區(qū)別殊霞,線程安全,資源加載的時(shí)機(jī),還有懶漢式為了實(shí)現(xiàn)線程安全的3種方式的細(xì)微差別。
參考:http://www.reibang.com/p/b84a251a8838
Our youth never dies,just fades away.

嗨~我是夏尼采龄章,一個(gè)有夢(mèng)想的IT男

每周輸出3篇有用的文章,目標(biāo)是簽約簡書锚贱。

如果文章對(duì)您有幫助晋修,希望能點(diǎn)個(gè)贊或者關(guān)注我。

您的關(guān)注和點(diǎn)贊是對(duì)我最大的鼓勵(lì)睁本,感謝您的閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皮假,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子哮笆,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歉胶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡漏策,警方通過查閱死者的電腦和手機(jī)巢寡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門谦絮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叫胖,“玉大人,你說我怎么就攤上這事∶耍” “怎么了式廷?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵俺陋,是天一觀的道長。 經(jīng)常有香客問我,道長苟鸯,這世上最難降的妖魔是什么砌梆? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮滤愕,結(jié)果婚禮上魂贬,老公的妹妹穿的比我還像新娘。我一直安慰自己勋锤,他們只是感情好蚕断,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布抱究。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亲怠。 梳的紋絲不亂的頭發(fā)上习勤,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天冬阳,我揣著相機(jī)與錄音,去河邊找鬼柒竞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛渡蜻,可吹牛的內(nèi)容都是我干的沦寂。 我是一名探鬼主播毯侦,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼试幽,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了腿短?” 一聲冷哼從身側(cè)響起赴魁,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎懦趋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疹味,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仅叫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了佛猛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惑芭。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖继找,靈堂內(nèi)的尸體忽然破棺而出遂跟,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布幻锁,位于F島的核電站凯亮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哄尔。R本人自食惡果不足惜假消,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岭接。 院中可真熱鬧富拗,春花似錦、人聲如沸鸣戴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窄锅。三九已至创千,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間入偷,已是汗流浹背追驴。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疏之,地道東北人殿雪。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像锋爪,于是被迫代替她去往敵國和親冠摄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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