如何實現一個單例模式

單例模式定義:

保證一個類只要一個實例,並提供一個訪問它的全局訪問點。

應用場景:

   如下圖,一般我們都會配置一下配置參數在文件conf.properties中,應用程序線程在運行的時候會先加載解析配置文件,將文件內容保存到數據對象conf.java中。通過這種方式,線程就可以訪問配置內容了。

這種場景有個很明顯的問題,就是每個線程要訪問配置文件的時候,都需要創建加載conf.properties配置文件創建conf對象。然而加載文件是個很耗時的過程,創建多個conf對象也浪費系統內存。其實我們只需要創建一個conf對象就夠了。那麼如何創建一個全局的conf對象呢,很顯然使用單例模式。

創建單例對象

創建單例對象注意要點

    在講如何創建單例對象之前,首選要講一下創建單例對象注意要點:

  1. 提供一個創建獲取對象的方法;
  2. 對象構造器使用private,不允許外部創建對象(枚舉類除外);
  3. 創建對象要線程安全;
  4. 獲取對象性能要高

 創建單例對象

餓漢式

  private static  final  SingletonPattern singleton =new SingletonPattern();
    public static SingletonPattern getSingleton(){
        return singleton;
    }

 餓漢式可以這樣理解,一個人已經很餓了,在幹活之前肯定要先喫飯了。對於應用程序來說,提供服務之前,就要先創建單例對象,調用方來獲取對象的時候直接返回創建好的對象,省去了創建對象的時間。

懶漢式

private static  SingletonPattern singleton1;
    public static synchronized SingletonPattern getSingleton1(){
        if (singleton1==null){
            return singleton1;
        }
        return  singleton1;
    }

懶漢式其實就是延遲加載,在需要的時候才創建。這種方式缺點是,每次獲取對象都要加同步鎖,性能很差。

雙重檢測

 private static volatile  SingletonPattern singleton2;
    public  static  SingletonPattern getInstance2(){
        if (singleton2 ==null){
            synchronized (SingletonPattern.class){
                if (singleton2==null){
                    singleton2=new SingletonPattern();
                }
            }
        }
        return singleton2;
    }

這種方式在對象爲空的時候才加鎖,很好的解決了懶漢式帶來的問題。volatile 保證可見性有序性,防止其他線程獲取到還未初始化完成的對象。

靜態內部類

   private static class   SingletonUtil{
        private static final SingletonPattern instance=new SingletonPattern();

    }
    private  static SingletonPattern getSingleton3(){
       return   SingletonUtil.instance;
    }

靜態內部類在訪問的時候纔會加載初始化,這種方式利用了靜態內部類的特性。

 

枚舉類

public enum SingletonEnum {

     Singleton ;
    private   SingletonPattern singletonPattern=new SingletonPattern();
    public SingletonPattern getSingletonPattern(){
        return  singletonPattern;
    }
  

    //獲取單例對象
    SingletonPattern singletonPattern = SingletonEnum.Singleton.getSingletonPattern();

枚舉類特性是每個類成員是全局唯一的,可以利用這種特性創建單例對象。

利用緩存創建對象

定義一個hashMap對象,獲取對象之前先從hashMap中獲取,獲取不到就創建對象,然後把創建的對象放入hashmap中。

 

總結

創建單例對象要注意一下上述所說的注意要點,考慮各種創建方式的優缺點,結合自己業務場景,選擇合適的創建模式。

 

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