設計模式(DesignPattern)之單例模式(SingleTon)

1、定義

        單例模式屬於創建型模式,確保一個類只有一個實例,並提供一個全局的訪問接口。

2、使用場景        

        在開發工程中,有些對象我們只需要一個:線程池、緩存、硬件設備等, 創建多個實例則會造成結果的不一致和資源的過多消耗。

3、UML類圖


4、經典的實現方式

1、懶漢模式
/**
 * 懶漢模式
 */
public class SingleTon01 {

    private static SingleTon01 instance;

    private SingleTon01() {
    }

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

        懶漢模式在使用的時候才進行實例化,在一定程度上節約了資源,但是在每次調用getInstance()都進行了同步,造成不必要的同步。

2、Double Check Lock(DCL)模式
/**
 * Double Check Lock(DCL)雙鎖檢測
 */
public class SingleTon02 {

    private volatile static SingleTon02 instance;

    /**
     * 構造方法私有化,不允許外部創建對象
     */
    private SingleTon02() {
    }

    public static SingleTon02 getInstance() {
        if (instance == null) {//第一次判空避免不必要的同步
            synchronized (SingleTon02.class) {
                if (instance == null) {//第二次判空爲了在null的情況下創建實例
                    instance = new SingleTon02();
                }
            }
        }
        return instance;
    }
    
}
    DCL是使用最多的一種實現單例的方式,但在《Java併發編程實戰》中提到這是一種"糟糕"的優化,在java1.5以前的版本中並沒有真正解決線程同步問題,在1.5版本以後可以加上volatile

3、靜態類部類模式
/**
 * 靜態類部類模式
 */
public class SingleTon03 {

    private SingleTon03() {
    }

    private static class SingletonHolder {
        private static final SingleTon03 instance = new SingleTon03();
    }

    public static SingleTon03 getInstance() {
        return SingletonHolder.instance;
    }

}
        這種方式不僅能夠保證線程安全,同時也能夠保證單例對象的唯一性,延遲單例對象的實例化。
 4、枚舉實現單例
/**
 * 枚舉單例
 */
public enum SingleTon04 {

    INSTANCE;

}
        枚舉對象的創建是現成安全的,並且也是唯一的。
5、利用容器實現單例
/**
 * 利用容器實現單例
 */
public class SingleTon05 {

    private static Map<String, Object> objMap = new HashMap<>();

    private SingleTon05() {}

    public void addObj(String key, Object instance) {
        if (!objMap.containsKey(key)) {
            objMap.put(key, instance);
        }
    }

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

}

        我們可以通過這種方式管理多種類型的管理,如對activity的管理。

5、總結

    優點:1、全局只有一個實例,減小了系統性能開銷。

    缺點:1、擴展困難,只能通過修改代碼的方式進行擴展。

              2、如果單例持有Context對象,容易造成內存泄漏問題,一般傳遞Application對象。


代碼:https://gitee.com/os2chen/DesignPattern


參考:《Head First Design》、《Android源碼設計模式解析與實戰》







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