設計模式系列 · 單例模式(最常見)

單例模式

關鍵點

1.構造函數不對外開放,一般爲Private
2.通過一個靜態方法或者枚舉返回單例類對象
3.確保單例類的對象有且只有一個,尤其在多線程環境下
4.確保單例類對象在反序列化時不會重新構建對象

實現方式

1.懶漢模式

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

優點:使用時實例化,一定程度節約資源。
缺點:第一次使用需要實例化,速度較慢,每次調用 getInstance 都進行同步,造成不必要的開銷。

2.Double Check Lock - DCL

public void class Singleton {
    private static Singleton sInstance = null;
    private Singleton () {}
    public static Singleton getInstance () {
        if (sInstance == null) {
            synchronized (Singleton.class) {
                if (sInstance == null) {
                     sInstance = new Songleton ();
                }
            }
        }
    }
    return sInstance;
}

優點:資源利用率高,第一次執行 getInstance 時纔會被實例化,效率高。
缺點:第一次加載較慢,會由於Java內存模型的原因偶爾失敗。高併發情況下也有缺陷,概率低。
造成失效原因(java編譯器允許亂序以及JDK1.5之前java內存模型中Cache、寄存器到主內存回寫順序的規定,1-2-3的順序無法保證,可能1-3-2.
JDK1.5或之後的版本加volatile規避)

1).給Singleton 的實例分配內存
2).調用Singleton() 的構造函數,初始化成員字段
3).將 sInstance 對象指向分配的內存空間

3.靜態內部類單例模式

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

優點:保證線程安全,確保唯一性,同時延遲了單例的實例化,推薦。

4.枚舉單例

public enum SingletonEnum {
    INSTANCE;
    public void doSomething () {
       System.out.println ("do some.");
    }
}

在上述的幾種單例模式中,反序列化時它們都會重新創建對象,枚舉不存在此問題。

5.使用容器作爲單例模式

public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String, Object> ();

private SingletonManager () {}
public static void registerService (String key, Object instance) {
    if(!objMap.containsKey(key) ) {
        objMap.put(key ,instance);
    }
}

public static Object getService (String, key) {
    return objMap.get(key);
    }
}

統一管理多種單例類型,降低耦合。

總結
優點:減少內存開支,性能開銷,避免對資源的多重佔用
*注意點:1) 拓展困難 . 2)若持有Context,防止內存泄露問題,傳入Application Context. *

發佈了24 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章