一天一種設計模式之三-----單例模式

一.單例模式定義

  1. 確保一個類只有一個實例,並且自行實例化並向整個系統提供這一個實例。
    java

  2. 主要優勢:提供了對惟一實例的受控訪問;因爲在系統內存中只存在一個對象,所以能夠節約系統資源,對於一些須要頻繁建立和銷燬的對象單例模式無疑能夠提升系統的性能。把構造方法都隱藏了,遵循了 迪米特法則;避免對共享資源的多重佔用;能夠全局訪問。
    c++

  3. 因爲單例模式中沒有抽象層,所以單例類的擴展有很大的困難,違背依賴倒置原則;濫用單例將帶來一些負面問題,如爲了節省資源將數據庫鏈接池對象設計爲的單例類,可能會致使共享鏈接池對象的程序過多而出現鏈接池溢出,單例類的職責太重,在必定程度上違背了「單一職責原則」。數據庫

  4. 適用場景:須要頻繁實例化而後銷燬的對象;建立對象耗時過多或者消耗資源過多,但又常常用到的對象;有狀態的工具類對象;頻繁訪問數據庫或文件的對象。安全

  5. 注意事項:多線程

    1. 只有單例類提供的方法獲得單例對象,不要使用反射,不然會實例化一個新對象(也就是說經過反射是能夠實例化多個單例類的),之前還聽人說能夠經過深拷貝,但clone方法默認是protect的,因此不用反射的話同樣作不到;ide

    2. 不要作斷開單例類對象與類中靜態引用的危險操做(靜態引用會存到java虛擬機的方法區,除非類文件被卸載,不然不會銷燬,但通常類的卸載條件很嚴苛,因此鏈接靜態引用的單例對象也會共存不會被gc收集);工具

    3. 多線程使用單例使用共享資源時,注意線程安全問題。性能

    4. java中餓漢模式要好於懶漢模式,c++中則通常使用懶漢式單例。測試

    5. 有的單例能夠被繼承,好比登記式單例,可參考登記式單例模式ui

  6. 單例能夠有七種模式(筆者所知,不包括上述登記式單例模式):這七種模式能夠參考以前轉發的博文:    單例的七種表達方式

  7. 今天回家太晚了,沒有把上面兩篇博文整理在這裏,抽空會整理的


二.測試代碼

  • 下面代碼用反射實現建立多個單例,至於問什麼輸出了4次,有興趣的同窗能夠看下虛擬機的類加載機制。各位晚安。

  •     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            Class clazz=Class.forName(SingleTon.class.getName());
            Constructor constructor=clazz.getDeclaredConstructors()[0];
            constructor.setAccessible(true);
            constructor.newInstance(new Object[]{});
            constructor.newInstance(new Object[]{});
            constructor.newInstance(new Object[]{});
        }
    }
    class SingleTon{
        private static SingleTon singleTon=new SingleTon();
        private SingleTon(){
            System.out.println("chuangjian");
        }
        public static SingleTon getInstance(){
            return singleTon;
        }
    }
相關文章
相關標籤/搜索