單例的幾種常見寫法

小追兵專欄

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

第一種:餓漢式

public class Singleton { 
    //實(shí)例化該單例對(duì)象。 
    private  static Singleton singleton=new Singleton(); 
    //私有化構(gòu)造方法,使不能在別的類中new對(duì)象 
    private Singleton() {  
    }  
    //對(duì)外提供的一個(gè)獲取該實(shí)例的方法
    public static Singleton getInstance() {  
       return singleton;  
    }  
} 

常見餓漢式就這種寫法,不存在多線程同步等問題??墒谴嬖谝粋€(gè)問題,在類被加載的時(shí)候,就初始化了對(duì)象。即便我們還沒想要用這個(gè)對(duì)象。下面 第三種 我們解決這個(gè)問題。

第二種:懶漢式

public class Singleton {  
    //volatile關(guān)鍵字,解決多處理器共享變量問題,防止編譯器對(duì)代碼進(jìn)行優(yōu)化,這個(gè)關(guān)鍵詞的解釋較為復(fù)雜,可以自行百度
    private volatile static Singleton singleton;  
  
    //私有化構(gòu)造方法,不讓new出其他對(duì)象。
    private Singleton() {  
    }  
  
    //暴露的獲取這個(gè)單例對(duì)象的方法
    public static Singleton getInstance() {  
        
        //判斷是否被實(shí)例化
        if (null == singleton) {  
            //同步鎖,放在判斷空的里面,是為了解決性能問題,這樣只有在new的時(shí)候走一次同步鎖,不用每次獲取實(shí)例的時(shí)候走到這里。
            synchronized (Singleton.class) {  
                //雙重判空,這個(gè)必須要有,因?yàn)榧僭O(shè)第一個(gè)線程進(jìn)入了第一個(gè)判空之后,離開了并保存現(xiàn)場,沒來得及創(chuàng)建對(duì)象,
                //這時(shí)第二個(gè)線程進(jìn)入了,順利的實(shí)例化了對(duì)象離開了。此時(shí)前面離開的線程回來后,又創(chuàng)建了一個(gè)對(duì)象;
                //這樣就有多個(gè)對(duì)象存在。
                if (null == singleton)  
                    singleton = new Singleton();  
            }  
        }  
        return singleton;  
    }  
}  

第三種:餓漢式升級(jí)版

public class Singleton {  
     
    private Singleton() {  
    }  
    public static Singleton getInstance() {  
       return SingletonHolder.SINGLETON;  
    }  

    //靜態(tài)內(nèi)部類,解決了我們只有在調(diào)用getInstance方法后,才去創(chuàng)建這個(gè)單例實(shí)例的需求。不會(huì)因?yàn)榧虞d這個(gè)類就創(chuàng)建實(shí)例,解決第一種方法的缺點(diǎn)。
    private static class SingletonHolder{  
        private  static Singleton SINGLETON=new Singleton();  
    }  
      
}  

第四種:枚舉式

大神為我們提供了一種不太好理解的方法,并且推薦使用。如下。

public enum Singleton {  
    INSTANCE;  
  
    private Singleton() {  
    }  
  
    public String[] getName() {  
        final String[] names = new String[3];  
        names[0] = "小白";  
        names[1] = "小彩";  
        names[2] = "小麗";  
        return names;  
    }  
  
} 
 

在activity中這樣調(diào)用:

Log.e("猜猜我喜歡誰:",Singleton.INSTANCE.getName()[2]);

注:

  • 我們使用單例,不一定是最好的,因?yàn)閜rivate構(gòu)造方法后,可以避免new一個(gè)新對(duì)象,可是避免不了通過反射機(jī)制創(chuàng)建個(gè)新對(duì)象啊。

  • 還有我們用的說的第一種餓漢式,是在類被加載的時(shí)候,創(chuàng)建的實(shí)例對(duì)象,可是如果有兩個(gè)類加載器呢,就不能保證對(duì)象的唯一性了。

  • 可是我們?cè)诒仨毷褂脝卫臅r(shí)候,我們?yōu)榱吮苊獠槐匾腻e(cuò)誤,這里我們優(yōu)先選擇雙重鎖,靜態(tài)內(nèi)部類,大神特別推薦使用枚舉。我覺得能高效解決問題的方法就是好方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單、最易理解的設(shè)計(jì)模式,也因?yàn)樗暮啙嵰锥?,是?xiàng)目中最...
    成熱了閱讀 4,545評(píng)論 4 34
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,727評(píng)論 18 399
  • 學(xué)js和python 練習(xí)英語
    安了靜了點(diǎn)閱讀 134評(píng)論 0 0

友情鏈接更多精彩內(nèi)容