枚舉實現單例模式


 

1.引言

單元素的枚舉類型已經成為實現Singleton的最佳方法
                      -- 出自 《effective java》

2.單例模式的特點

  • 單例模式三個主要特點:
    1、構造方法私有化;
    2、實例化的變量引用私有化;
    3、獲取實例的方法共有。

3. 常用的單例模式

1.單例的餓漢模式

 1 public class Singleton { 2 /* 3 * 利用靜態變量來記錄Singleton的唯一實例 4 * 直接初始化靜態變量,這樣就可以確保線程安全了 5 */ 6 private static Singleton uniqueInstance = new Singleton(); 7 8 /* 9 * 構造器私有化,只有Singleton類內才可以調用構造器 10 */ 11 private Singleton(){ 12 13 } 14 15 public static Singleton getInstance(){ 16 return uniqueInstance; 17 } 18 19 } 

2.懶漢的雙重加鎖機制

 1 public class Singleton { 2 /* 3 * 利用靜態變量來記錄Singleton的唯一實例 4 * volatile 關鍵字確保:當uniqueInstance變量被初始化成Singleton實例時, 5 * 多個線程正確地處理uniqueInstance變量 6 * 7 */ 8 private volatile static Singleton uniqueInstance; 9 10 /* 11 * 構造器私有化,只有Singleton類內才可以調用構造器 12 */ 13 private Singleton(){ 14 15 } 16 17 /* 18 * 19 * 檢查實例,如果不存在,就進入同步區域 20 */ 21 public static Singleton getInstance(){ 22 if(uniqueInstance == null){ 23 synchronized(Singleton.class){ //進入同步區域 24 if(uniqueInstance == null){ //在檢查一次,如果為null,則創建 25 uniqueInstance = new Singleton(); 26 } 27 } 28 } 29 30 return uniqueInstance; 31 } 32 33 } 

3.靜態內部類

public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } } 

4.為什么使用單例

4.1 私有化構造器並不保險

    《effective java》中只簡單的提了幾句話:“享有特權的客戶端可以借助AccessibleObject.setAccessible方法,通過反射機制調用私有構造器。如果需要低於這種攻擊,可以修改構造器,讓它在被要求創建第二個實例的時候拋出異常。

4.2序列化問題

    任何一個readObject方法,不管是顯式的還是默認的,它都會返回一個新建的實例,這個新建的實例不同於該類初始化時創建的實例。”當然,這個問題也是可以解決的,想詳細了解的同學可以翻看《effective java》第77條:對於實例控制,枚舉類型優於readResolve

4.3 枚舉單例示例

public enum EnumSingleton { INSTANCE; public EnumSingleton getInstance(){ return INSTANCE; } } 

完整的枚舉單例


public class User { //私有化構造函數 private User(){ } //定義一個靜態枚舉類 static enum SingletonEnum{ //創建一個枚舉對象,該對象天生為單例 INSTANCE; private User user; //私有化枚舉的構造函數 private SingletonEnum(){ user=new User(); } public User getInstnce(){ return user; } } //對外暴露一個獲取User對象的靜態方法 public static User getInstance(){ return SingletonEnum.INSTANCE.getInstnce(); } } public class Test { public static void main(String [] args){ System.out.println(User.getInstance()); System.out.println(User.getInstance()); System.out.println(User.getInstance()==User.getInstance()); } } 結果為true 

5.總結

至此,相信同學們應該能明白了為什么Joshua Bloch說的“單元素的枚舉類型已經成為實現Singleton的最佳方法”了吧。



作者:多彩海洋
鏈接:https://www.jianshu.com/p/d35f244f3770
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM