單例模式的五種實現方式

單例模式可以說是23中設計模式中應用最廣的一種模式了。  

      定義:確保某一個類只有一個實例,自行實例化並且想整個系統提供這個實例。

      使用場景:避免某個類產生多個對象而消耗過多的資源,確保某個類在程序中只有一個實例。比如我們使用的圖片加載器ImageLoader。往往單例創建的對象,耗費的資源都比較多,所以在初始化單例對象的時候就顯得尤爲重要了,接下來,我們就來聊一聊單例的幾種實現方式。

一、餓漢式

[java] view plain copy

  1. public class ImageLoader{  

  2.   

  3.      private static ImageLoader instance = new ImageLoader;  

  4.      private ImageLoader(){}  

  5.      public static ImageLoader getInstance(){   

  6.        return instance;   

  7.   }  

  8. }  




餓漢式顧名思義,就是這個漢子很餓,一上來就把單例對象創建出來了,要用的時候直接返回即可,這種可以說是單例模式中最簡單的一種實現方式。但是問題也比較明顯。單例在還沒有使用到的時候,初始化就已經完成了。也就是說,如果程序從頭到位都沒用使用這個單例的話,單例的對象還是會創建。這就造成了不必要的資源浪費。所以不推薦這種實現方式。


二、懶漢式


[java] view plain copy

  1. public class ImageLoader{  

  2.      private static ImageLoader instance;  

  3.      private ImageLoader(){}  

  4.      public static synchronized ImageLoader getInstance(){   

  5.             if(instance == null){   

  6.                  instance = new ImageLoader();   

  7.            }   

  8.             return instance;  

  9.       }  

  10. }  



餓漢式也顧名思義,就是這個漢子比較懶,一開始的時候什麼也不做,知道要使用的時候採取創建實例的對象。看起來還不錯,只有在使用實例的時候,我們纔回去創建對象。但是細心的同學可能發現了,我們在獲取實例的方法上加了鎖,避免多線程引發的創建多個單例的情況。多線程的問題是避免了,但也造成了整體性能的下降,每次使用單例對象,都需要鎖判斷,降低了整體性能。很明顯,懶漢式也不是我們所要追求的目標。


三、Double CheckLock實現單例

英文稍好點的東西,應該都看懂了,DCL也就是雙重鎖判斷機制,直接上代碼。


[java] view plain copy

  1. public class ImageLoader{  

  2.      private static ImageLoader instance;  

  3.      private ImageLoader(){}  

  4.      public static ImageLoader getInstance(){  

  5.            if(instance == null){  

  6.                    synchronized (ImageLoader.class){  

  7.                         if(instance == null){  

  8.                            instance = new ImageLoader();  

  9.                            }  

  10.                     }  

  11.              }   

  12.              return instance;   

  13.         }  

  14. }  



可以看到,在獲取單例對象的時候,我們先進行了兩爲空判斷,並且在第二次判斷前加了鎖,這就讓程序變得更加優秀,在使用的時候,只會前幾次獲取單例對象的時候會進行鎖判斷,一旦單例對象創建完成,鎖的任務也就完成了,在懶漢式的基礎上,提高了性能。DCL是使用最多的單例實現方式,能夠在使用的時候才進行單例對象的初始化創建,並且能夠在絕大多數情況下保證對象的唯一性的正確性。請注意,是絕大多數情況下,也就是說,這種模式也不能完全保證單例的對象的完美實現,但是,就一般情況下,這種模式都能滿足需求。俗話說,學無止境,接下來我們就來看看單例模式的終極實現版本。


四、靜態內部類實現模式

直接上代碼


[java] view plain copy

  1. public class ImageLoader{  

  2.     private static class InnerInstance{  

  3.        private static final ImageLoader instance = new ImageLoader();  

  4.     }  

  5.     private ImageLoader(){}  

  6.     public static ImageLoader ImageLoader(){  

  7.         return InnerInstance.instance;  

  8.    }  

  9. }  



可以發現這種方式,並未加鎖,因爲第一次加載ImageLoader類時,並不會實例化單例對象,只有第一次調用getInstance()方法時會導致虛擬機加載InnerInstance類,這種
方式不僅能保證對象的單一性,還避免加鎖帶來的性能問題,又啓動了延遲加載的優化,所以這就是單例模式的終極實現版本,也是推薦使用的方式。


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