瞭解23種設計模式之單例模式

一,什麼是單例模式?

        單例模式是一種對象創建型模式,使用單例模式,可以保證爲一個類只生成唯一的實例對象。也就是說,在整個程序空間中,該類只存在一個實例對象。

         其實,GoF( Gang of Four,代表意思是 設計模式一書,四個作者,被稱爲四人組)對單例模式的定義是: 保證一個類,只有一個實例存在,同事提供能對該實例加以訪問的全局訪問方法。

二,爲什麼要使用單例模式呢?

在開發中,我們常常有以下需求:

-在多個線程之間,比如servlet 環境,共享同一個資源或者操作同一個對象

-在整個程序中使用全局變量,共享資源。

-在整個系統中,爲了性能的考慮,需要節省對象的創建時間等等

Singleton模式可以保證爲了一個類只生成唯一的實例對象。

三,單例模式實現。

3.1 餓漢式。

public class Singleton {

    //餓漢式單例模式
    private static final Singleton singleton = new Singleton();

    /**
     * 私有化構造方法
     */
    private Singleton() {
    }

    /**
     * 提供一個全局的靜態方法
     * @return
     */
    public  static Singleton getSingleton() {
        return singleton;
    }
}

3.2 懶漢式。

public class SingletonLazy {

    /**
     *
     */
    private static  SingletonLazy singletonLazy;

    /**
     * 構造方法實例化
     */
    private SingletonLazy() {
    }

    /**懶漢模式,在不需要的時候並不會去創建實例,只有在真正調用的時候
     * 提供給外部的靜態方法纔去實例化
     * @return
     */
    private static  SingletonLazy getInstance(){
        if(singletonLazy ==null){
            return new SingletonLazy();
        }
        return singletonLazy;
    }
}

3.3 雙重檢查。

public class SingletonCheck {

    private volatile static SingletonCheck singletonCheck;

    /**
     * 構造方法實例化
     */
    private SingletonCheck() {
    }


    /**
     *
     * 雙重檢查,在多線程的環境下,會出現資源競爭。
     * 在 A線程剛進入 if 判斷的時候, B線程 就已經實例化了。這時候 我們需要加上 synchronized  (同步),
     * 這樣能保證 A線程執行完方法體,B線程 才能執行。
     * synchronized 放在 if 裏面 是爲了節省性能,在需要線程同步的地方去做線程同步。 第一重檢查
     * 第二重檢查, 當 A,B線程先後進入if 判斷都是null時,都會去 肯定有一個線程阻塞在 if判斷這裏,
     * 只有當另一個線程 去實例化完成之後, 另一個線程 纔會去 實例化,但是 之前已經有一個實例化對象了,
     * 現在又出現兩次實例化對象,肯定是不符合我們的初衷的,所以在  同步方法內 在做一次檢查,對象是否爲空,
     * 這就是雙重檢查
     * @return
     */
    private static  SingletonCheck getInstance(){
        if(singletonCheck ==null){
            synchronized (SingletonCheck.class) {
                if(singletonCheck ==null) {
                    singletonCheck = new SingletonCheck();
                }
            }
        }
        return singletonCheck;
    }
}

3.4靜態內部類單例模式

public class SingletonStatic {

    private SingletonStatic(){
    }

    /**
     * 只有第一次調用getInstance方法時,虛擬機才加載 Inner 並初始化instance ,只有一個線程可以獲得對象的初始化鎖,
     * 其他線程無法進行初始化,保證對象的唯一性。目前此方式是所有單例模式中最推薦的模式,但具體還是根據項目選擇。
     */
    public static SingletonStatic getInstance(){
        return Inner.instance;
    }
    
    private static class Inner {
        private static final SingletonStatic instance = new SingletonStatic();
    }
}

3.5 枚舉單例模式

public enum  SingletonEnum {

    INSTANCE;

    /** 默認枚舉實例的創建是線程安全的,並且在任何情況下都是單例
     * 枚舉單例模式在《Effective Java》中推薦的單例模式之一。但枚舉實例在日常開發是很少使用的,就是很簡單以導致可讀性較差。
     * @return
     */
    public static SingletonEnum getInstance() {
        return SingletonEnum.INSTANCE;
    }
}

推薦:使用 3.4靜態內部類單例模式,直觀,簡潔,同樣是線程安全的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章