1. 程式人生 > >單例模式的六種實現和簡單介紹

單例模式的六種實現和簡單介紹

    在實際開發中,我們常會需要使用到單例模式。單例模式的核心就是,一個類只有一個例項。

    如何實現只有一個例項呢?關鍵是:建構函式的私有化。

    單例模式的實現有很多中,這裡介紹一下常見的六種。

    和其他介紹單例的不一樣。我們首先介紹一種不常用的,但是我認為很有潛力,以後的單例實現最常用的方式。那就是使用列舉來實現單例模式。然後才是其他幾種實現。上程式碼:

    (1)列舉實現單例:

public enum Singleton {
    INSTANCE;
    public void showMessage(){
        System.out.println("列舉");
    }
}

        是不是超簡單?超級清晰?使用的時候直接Singleton.INSTANCE。就可以了。

        因為這種方式在JDK1.5之後才支援,所以在一些老系統上可能不能用。但是現在JDK10都出來了,所以我認為以後這種方式會最常用。為什麼:1.很簡潔,甚至簡單。2.自動支援序列化機制。3.絕對防止被多次例項化。4.執行緒安全。

        Perfect!

        (2)懶漢式執行緒不安全:

public class Singleton {
    private static Singleton instance;

    private Singleton(){}

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

        很簡單的一種單例模式,(當然,列舉更簡單)很容裡理解:靜態私有的實體類,私有的構造方法,提供get方法,只需要在第一次呼叫的時候例項化一次。

        但是缺點也很明顯,執行緒不安全。多執行緒的情況下就不能正常工作了。

        (3)懶漢式執行緒安全:

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

        和第二種方式的唯一區別就是:在get方法加了鎖synchronized。這樣就執行緒安全了。但是缺點也很明顯,使用鎖之後效能降低了。

        (4)餓漢式:

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

        餓漢式基於classloder的機制實現了執行緒安全。但是在類裝載的時候就載入了例項,浪費記憶體,也不滿足lazy loading的效果。

        餓漢式和懶漢式可以見名知義地理解為:懶漢,他很懶,你不去找他他就不給你例項化。餓漢就是餓慌了,你不去找他他都給你例項化好了。

        (5)雙重校驗鎖:

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

        採用雙鎖機制實現單例,多執行緒下也保證安全和高效。但是呢,缺點也很明顯:很複雜。至少對我來說,雙重校驗鎖什麼的根本不明白啊。照著寫還行,要我解釋就···弄不懂了。

        (6)靜態內部類:

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

        和雙重校驗鎖一樣的效果,但是簡單一些。也是用classloder的機制實現執行緒安全。且類載入的時候不一定例項化單例。

        總結:通常情況下,餓漢式的單例已經能滿足日常使用了。有特殊需要的時候可以考慮雙重校驗鎖。有反序列化建立愛你物件的需求的時候使用列舉。不過了,就個人而言,我更喜歡列舉的方式。正如前面所說:1.簡潔。2.支援序列化。3.絕對單例。4.執行緒安全。Perfect!

        差不多就是這樣,希望大家能找到自己喜歡、工作適用的單例模式。

        最後呢,作者水平有限,有什麼問題大家可以提出來共同探討學習。

        差不多就是這樣,祝大家學習愉快。謝謝。

                                                                      —— by:軒轔 ——