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
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。