確保某個類只有一個實例,並且自行實例化並向整個系統提供這個實例。java
- Client:高層客戶類
- Singleton:單例類
- 構造函數不對外開放,通常爲Private
- 經過一個靜態方法或枚舉返回單例類對象
- 確保單例類的對象有且只有一個,尤爲在多線程環境下
- 確保單例類對象在反序列化時不會從新構建對象
- 餓漢:在聲明時就初始化
/** * 餓漢單例 */ public class MySingleton { // 餓漢單例,在聲明時就初始化 private static MySingleton ourInstance = new MySingleton(); public static MySingleton getInstance() { return ourInstance; } private MySingleton() { } }- 懶漢:只有在使用時纔會實例化,在必定程度上節省了資源;缺點是第一次加載時須要及時進行實例化,反應稍慢,最大的問題是每次調用getInstance都要進行同步,形成沒必要要的同步開銷。這種模式通常不建議採用。
/** * 懶漢單例 */ public class MySingleton { private static MySingleton ourInstance; public static synchronized MySingleton getInstance() { // 懶漢單例,只有在使用纔會實例化 if (ourInstance == null) { ourInstance = new MySingleton(); } return ourInstance; } private MySingleton() { } }- DCL:Double Check Lock。優勢是既可以在須要時實例化單例,又能保證線程安全,且單例對象初始化後調用getInstance不進行同步鎖。
/** * Double Check Lock(DCL) */ public class MySingleton { private static MySingleton ourInstance = null; private MySingleton() {}; public static MySingleton getInstance() { // 避免沒必要要的同步 if (ourInstance == null) { synchronized (MySingleton.class) { // 建立實例 if (ourInstance == null) { ourInstance = new MySingleton(); } } } return ourInstance; } }- 靜態內部類:當第一次加載Singleton類時並不會初始化,只有在第一次調用時纔會初始化。所以,第一次調用getInstance方法會致使虛擬機加載SingleHolder類,這種方式不只可以確保線程安全,也能保證單例對象的惟一性,同時也延遲了單例實例化,因此這是推薦使用的單例模式實現方式。
/** * 靜態內部類單例模式 */ public class MySingleton { private MySingleton() {}; public static MySingleton getInstance() { return SingletonHolder.ourInstance; } /** * 靜態內部類 */ private static class SingletonHolder { private static MySingleton ourInstance = new MySingleton(); } }- 枚舉單例:枚舉單例是線程安全的,而且在任何狀況下它都是一個單例。且沒法經過反序列化獲得對象。
/** * 枚舉單例 */ public enum SingletonEnum { INSTANCE; public void dosomething() { System.out.println("do sth."); } }- 使用容器實現單例
/** * 使用容器實現單例模式 */ public class SingletonManager { private static Map<String, Object> objMap = new HashMap<>(); private SingletonManager() {} public static void registerService(String key, Object instance) { if (!objMap.containsKey(key)) { objMap.put(key, instance); } } public static Object getService(String key) { return objMap.get(key); } }
getSystemService 經過容器實現單例 安全