設計模式——單例模式

感謝 12

一、什麼是單例

單例提供了一種創建對象的方式,確保只有單個對象被創建,設計目的是保證整個應用中有且只有一個實例

優點
  • 節約資源
  • 不用頻繁的創建對象,一定程度減少內存泄漏和內存溢出的風險

二、設計思想

要保證整個應用中只有一個實例,要保證

1、不允許其他程序 new 對象

因爲每次new都會產生一個新的對象,這樣保證不了對象的唯一性。

2、在該類中創建對象

有了1的前提,那new對象的事只能交給本類來做,在類的內部,new一個對象

3、對外提供獲取對象的方法

對象在本類中創建,其他類要調用的話,需要在本類中提供一個方法可讓其他類進行調用對象

二、實現步驟

基於上面的設計思想,具體實現步驟如下:

  1. 構造函數私有化
  2. 在本類中 new 一個對象
  3. 提供一個靜態方法獲取實例(注意多線程問題)

三、實現方式

1、餓漢式(線程安全)
public class Singleton1 {
    
    private static final Singleton1 INSTANCE = new Singleton1();

    //  提供靜態方法獲取實例
    public static Singleton1 getInstance() {
        return INSTANCE;
    }
}
  • 優點:簡單粗暴、類加載的時候就初始化完成,線程安全
  • 缺點:不可延遲加載,類加載時就初始化,可能會造成不必要的內存浪費
2、懶漢式(線程不安全)
public class Singleton2 {

    private static Singleton2 instance;

    // 構造函數私有化
    private Singleton2() {

    }
    // 提供靜態方法獲取實例
    public static Singleton2 getInstance() {
        if (instance == null) {
            instance = new Singleton2();
        }
        return instance;
    }
}
  • 優點:延遲初始化,減少不必要內存消耗
  • 缺點:線程不安全
3、懶漢式(線程安全,同步方法)
public class Singleton3 {
    
    private Singleton3() {

    }
    private static Singleton3 instance;

    public static synchronized Singleton3 getInstance() {
        if (instance == null) {
            instance = new Singleton3();
        }
        return instance;
    }
}
  • 優點:延遲初始化,減少不必要內存消耗,線程安全
  • 缺點:效率偏低,每次獲取實例都進行同步鎖,事實上只需要在第一次new對象的時候同步鎖就行了,後續想獲取實例可以直接返回。
4、懶漢式(線程安全,同步代碼塊)(DCL 雙重檢查)
public class Singleton4 {
    // volatile : 防止指令重排序
    private volatile static Singleton4 instance;
    private Singleton4() {

    }
    
    public static Singleton4 getInstance() {
        if (instance == null) {
            synchronized (Singleton4.class) {
                if (instance == null) {
                    instance = new Singleton4();
                }
            }
        }
        return instance;
    }
}
  • 優點:延遲初始化,減少不必要內存消耗,線程安全,裝逼大佬推薦使用這個
5、靜態內部類
public class Singleton5 {

    private static final class SingletonHolder {
        private static final Singleton5 INSTANCE = new Singleton5();
    }

    public static Singleton5 getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

推薦使用

6、枚舉
public enum Singleton6 {
    INSTANCE;
    String getMethod() {
        return "枚舉單例";
    }
    // 方法調用: Singleton6.INSTANCE.getMethod()
}

《Effective Java》中推薦的模式 ,但是閱讀性不高,Android中使用枚舉會有一定的內存開銷

四、總結

線程安全 併發性能好 延遲初始化 序列化/反序列化安全 能抵禦反射攻擊
餓漢式 Y Y
懶漢式 不加鎖 Y Y
懶漢式(加鎖的) Y Y
DCL(雙重檢查) Y Y Y
靜態內部類 Y Y Y
枚舉 Y Y Y Y

4、5、6 都是推薦使用的,但是6的話,在Android中用的人不多,4的話從代碼上反應出來了怎麼解決懶加載和線程安全問題。

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