android設(shè)計(jì)模式之單例模式

(其實(shí)設(shè)計(jì)模式應(yīng)該從屬于java伶跷,但是會(huì)專門針對(duì)android做相應(yīng)的解釋,所以就取名為android設(shè)計(jì)模式~)

一.單例模式的介紹

單例模式是應(yīng)用最廣的模式之一,在應(yīng)用這個(gè)模式的時(shí)候盾沫,單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在。在android中的應(yīng)用場(chǎng)景例如整個(gè)app只有一個(gè)application對(duì)象殿漠,只有一個(gè)ImageLoader對(duì)象等赴精。

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

1.餓漢模式

public class Singleton {  
   private Singleton() {}  //在該類初始化的時(shí)候就會(huì)自行實(shí)例化                           
   private static final Singleton single = new Singleton();   
   public static Singleton getInstance() {  
      return single;  
   } 
} 

2.懶漢模式

public class Singleton { 
    private Singleton(){} 
    private final static Singleton mInstance; //沒有care線程安全的問題 
    public static Singleton getInstance() { 
        if(mInstance == null){ 
            mInstance = new Singleton(); 
        } 
        return mInstance; 
    }
}

Tips:不論是餓漢模式還是懶漢模式,可能在你的app中都占有一席之地绞幌。那么我們先來對(duì)比下兩者的區(qū)別蕾哟,首先餓漢模式會(huì)在該類初始化的時(shí)候就自動(dòng)實(shí)例化,而懶漢模式則會(huì)在對(duì)應(yīng)調(diào)用getInstance方法時(shí)才會(huì)對(duì)應(yīng)的實(shí)例化莲蜘,實(shí)現(xiàn)了實(shí)例的延時(shí)加載谭确。設(shè)想如果該實(shí)例在app中不一定被使用到,那么使用懶漢模式就可以節(jié)省內(nèi)存票渠。但是懶漢模式會(huì)在第一次獲取實(shí)例時(shí)較為耗時(shí)逐哈,餓漢模式由于在初始化類時(shí)就進(jìn)行了實(shí)例化,第一次獲取實(shí)例就不會(huì)耗時(shí)问顷。

以上是針對(duì)餓漢模式和懶漢模式之間的區(qū)別做的分析昂秃,接下來我們來關(guān)注之前代碼中對(duì)于懶漢模式線程不安全的問題薯鼠。分別提供以下幾種解決方案來進(jìn)行對(duì)比:

2.1.在getInstance方法上加同步鎖

public class Singleton { 
     private Singleton(){} 
     private final static Singleton mInstance; //加上同步鎖 
     public static synchronized Singleton getInstance() { 
        if(mInstance == null){ 
             mInstance = new Singleton(); 
        } 
        return mInstance; 
     }
}

這種方法雖然解決了線程安全的問題,但是單例模式一般都是應(yīng)用在一些會(huì)被頻繁調(diào)用的場(chǎng)景上的械蹋,如果在每次獲取實(shí)例的時(shí)候都需要去進(jìn)行線程同步出皇,那會(huì)增加不小的開銷,會(huì)使單例的獲取變的緩慢哗戈,這樣就得不償失了郊艘。那么我們繼續(xù)改進(jìn),看下面的方法:

2.2.Double Check Lock(DCL)實(shí)現(xiàn)單例

public class Singleton { 
     private Singleton(){} 
     private final static Singleton mInstance; 
     /*雙重鎖定:只在第一次初始化的時(shí)候加上同步鎖*/  
     public static Singleton getInstance() { 
          if(mInstance == null){ 
              synchronized(Singleton.class){ 
                  if(mInstance == null){ 
                        mInstance = new Singleton(); 
                  }
              }
         } 
         return mInstance; 
     }
}```
這種雙重鎖定的方式唯咬,避免了每次獲取實(shí)例時(shí)不必要的同步操作纱注,只在第一次獲取實(shí)例的時(shí)候才進(jìn)行同步,將開銷減到了最小胆胰,并且保證了線程安全狞贱。但是,真的是線程安全了么蜀涨?問題其實(shí)出在mInstance = new Singleton();這句代碼瞎嬉,雖然它只是一句代碼,但是實(shí)際上它不是一個(gè)原子操作厚柳,這句代碼最終會(huì)被編譯成多條匯編指令氧枣,它大致做了3件事情:
(1)給Singleton的實(shí)例分配內(nèi)存;
(2)調(diào)用Singleton()的構(gòu)造函數(shù),初始化成員字段;
(3)將mInstance對(duì)象指向分配的內(nèi)存空間(此時(shí)mInstance就不是null了)别垮。
由于Java編譯器允許處理器亂序執(zhí)行便监,以及JDK1.5之前JMM(Java Memory Model,即Java內(nèi)存模型)中Cache碳想、寄存器到內(nèi)存回寫順序的規(guī)定烧董,上面的第二和第三的順序是無法保證的。也就是說胧奔,執(zhí)行順序可能是1-2-3也可能是1-3-2逊移。如果是后者,并且在3執(zhí)行完畢葡盗、2未執(zhí)行之前螟左,被切換到另一個(gè)線程上啡浊,就會(huì)出問題觅够。但是在你的app沒有太多的高并發(fā)存在時(shí),這種模式已經(jīng)可以完全滿足大多數(shù)開發(fā)者的需求巷嚣。那么一定還有更好的:
#### 2.3.靜態(tài)內(nèi)部類單例模式
```java
public class Singleton { 
     private Singleton(){} 
     private final static Singleton mInstance; 
     public static Singleton getInstance() { 
         return SingletonHolder.mInstance; 
     } 
     private static class SingletonHolder { 
         private final static Singleton mInstance = new Singleton(); 
     }
}

當(dāng)?shù)谝淮渭虞dSingleton類的時(shí)候并不會(huì)初始化mInstance喘先,只有在第一次調(diào)用getInstance方法時(shí)才會(huì)導(dǎo)致mInstance被初始化。因此廷粒,第一次調(diào)用getInstance方法會(huì)導(dǎo)致虛擬機(jī)加載SingletonHolder類窘拯,這種方式不僅能夠確保線程安全红且,也能夠保證單例對(duì)象的唯一性,同時(shí)也延遲了單例的實(shí)例化涤姊,所以這是推薦使用的單例模式實(shí)現(xiàn)方式暇番。Tip:java中的枚舉其實(shí)也是單例的一種實(shí)現(xiàn)方式

三.結(jié)論

之前在對(duì)單例的了解并沒有特別的系統(tǒng),這次梳理了下思喊,發(fā)現(xiàn)其實(shí)自己的工程中還是有很多不考慮線程安全的單例實(shí)現(xiàn)的壁酬,雖然在沒有并發(fā)的情況下可能沒有太大的影響,但是程序是需要有超前意識(shí)的恨课,推薦大家也使用2.3的單例實(shí)現(xiàn)方式舆乔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市剂公,隨后出現(xiàn)的幾起案子希俩,更是在濱河造成了極大的恐慌,老刑警劉巖纲辽,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颜武,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡拖吼,警方通過查閱死者的電腦和手機(jī)盒刚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绿贞,“玉大人因块,你說我怎么就攤上這事〖” “怎么了涡上?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拒名。 經(jīng)常有香客問我吩愧,道長(zhǎng),這世上最難降的妖魔是什么增显? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任雁佳,我火速辦了婚禮,結(jié)果婚禮上同云,老公的妹妹穿的比我還像新娘糖权。我一直安慰自己,他們只是感情好炸站,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布星澳。 她就那樣靜靜地躺著,像睡著了一般旱易。 火紅的嫁衣襯著肌膚如雪禁偎。 梳的紋絲不亂的頭發(fā)上腿堤,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音如暖,去河邊找鬼笆檀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛盒至,可吹牛的內(nèi)容都是我干的误债。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼妄迁,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼寝蹈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起登淘,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤箫老,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后黔州,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耍鬓,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年流妻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牲蜀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绅这,死狀恐怖涣达,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情证薇,我是刑警寧澤度苔,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站浑度,受9級(jí)特大地震影響寇窑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箩张,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一甩骏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧先慷,春花似錦饮笛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扎拣。三九已至赴肚,卻和暖如春素跺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背誉券。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來泰國打工指厌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人踊跟。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓踩验,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親商玫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子箕憾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

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

  • 一.什么是單例模式 單例模式的定義:確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)訪問他的全局訪問點(diǎn)拳昌。單例模式是幾個(gè)設(shè)計(jì)模式中...
    Geeks_Liu閱讀 2,230評(píng)論 0 10
  • 概述 單例模式是應(yīng)用最廣的模式之一袭异,在應(yīng)用這個(gè)模式時(shí),單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在炬藤。許多時(shí)候整個(gè)系統(tǒng)只需要...
    劉滌生閱讀 1,022評(píng)論 0 5
  • 作者:ivm 之前做android 項(xiàng)目時(shí)御铃,用的最多的就是設(shè)計(jì)模式,就是單例模式沈矿,用的時(shí)候上真,心里總有些疑問。今天呢...
    lovesosoi閱讀 12,085評(píng)論 12 18
  • 前言 本文主要參考 那些年羹膳,我們一起寫過的“單例模式”睡互。 何為單例模式? 顧名思義陵像,單例模式就是保證一個(gè)類僅有一個(gè)...
    tandeneck閱讀 2,517評(píng)論 1 8
  • 在日常開發(fā)過程中時(shí)常需要用到設(shè)計(jì)模式湃缎,但是設(shè)計(jì)模式有23種,如何將這些設(shè)計(jì)模式了然于胸并且能在實(shí)際開發(fā)過程中應(yīng)用得...
    AntDream閱讀 1,798評(píng)論 0 19