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

所謂單例,就是整個(gè)程序有且僅有一個(gè)實(shí)例。該類負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有一個(gè)對(duì)象被創(chuàng)建。在Java,一般常用在工具類的實(shí)現(xiàn)或創(chuàng)建對(duì)象需要消耗資源。
特點(diǎn)

  • 類構(gòu)造器私有
  • 持有自己類型的屬性
  • 對(duì)外提供獲取實(shí)例的靜態(tài)方法
    懶漢模式
    線程不安全,延遲初始化,嚴(yán)格意義上不是不是單例模式
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

餓漢模式
線程安全,比較常用,但容易產(chǎn)生垃圾,因?yàn)橐婚_始就初始化

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

雙重鎖模式
線程安全,延遲初始化。這種方式采用雙鎖機(jī)制,安全且在多線程情況下能保持高性能。

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

雙重檢查模式,進(jìn)行了兩次的判斷,第一次是為了避免不要的實(shí)例,第二次是為了進(jìn)行同步,避免多線程問題。由于singleton=new Singleton()對(duì)象的創(chuàng)建在JVM中可能會(huì)進(jìn)行重排序,在多線程訪問下存在風(fēng)險(xiǎn),使用volatile修飾signleton實(shí)例變量有效,解決該問題。

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

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

只有第一次調(diào)用getInstance方法時(shí),虛擬機(jī)才加載 Inner 并初始化instance ,只有一個(gè)線程可以獲得對(duì)象的初始化鎖,其他線程無法進(jìn)行初始化,保證對(duì)象的唯一性。目前此方式是所有單例模式中最推薦的模式,但具體還是根據(jù)項(xiàng)目選擇。
枚舉單例模式

public enum Singleton {
    INSTANCE;
}

默認(rèn)枚舉實(shí)例的創(chuàng)建是線程安全的,并且在任何情況下都是單例。實(shí)際上

  • 枚舉類隱藏了私有的構(gòu)造器。
  • 枚舉類的域 是相應(yīng)類型的一個(gè)實(shí)例對(duì)象
    那么枚舉類型日常用例是這樣子的:
public enum Singleton  {
    INSTANCE 
 
    //doSomething 該實(shí)例支持的行為
      
    //可以省略此方法,通過Singleton.INSTANCE進(jìn)行操作
    public static Singleton get Instance() {
        return Singleton.INSTANCE;
    }
}

枚舉單例模式在《Effective Java》中推薦的單例模式之一。但枚舉實(shí)例在日常開發(fā)是很少使用的,就是很簡單以導(dǎo)致可讀性較差。
在以上所有的單例模式中,推薦靜態(tài)內(nèi)部類單例模式。主要是非常直觀,即保證線程安全又保證唯一性。
眾所周知,單例模式是創(chuàng)建型模式,都會(huì)新建一個(gè)實(shí)例。那么一個(gè)重要的問題就是反序列化。當(dāng)實(shí)例被寫入到文件到反序列化成實(shí)例時(shí),我們需要重寫readResolve方法,以讓實(shí)例唯一。

private Object readResolve() throws ObjectStreamException{
        return singleton;
}
最后編輯于
?著作權(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)容

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