精講Android設計模式-單例模式
原文連結
更多教程
為什麼要使用單例模式
單例的優點
1.只有一個例項,節省開銷
2.全域性使用方便,同時避免頻繁建立和銷燬
使用單例的注意點:
要避免造成記憶體洩漏
常用的單例模式
單例不僅要滿足執行緒安全 ,還要注意防止序列化產生新物件 。如果單例實現了Serializable介面,就必須加入如下方法(列舉單例不用這麼做,因為JVM能保障這點):
private Object readResolve()throws ObjectStreamException{ return INSTANCE; }
原文連結
更多教程
餓漢式
餓漢式:就是在類初始化時就例項化 ,所以是執行緒安全的。
缺點是:
1.沒有懶載入,在不需要的時候也會被例項化,造成記憶體浪費。
2.例項化方法對外部呼叫不友好,傳參不方便
public class Singleton implements Serializable { private static final Singleton INSTANCE = new Singleton(); // 私有化建構函式 private Singleton(){} public static Singleton getInstance(){ return INSTANCE; } /** * 如果實現了Serializable, 必須重寫這個方法 */ private Object readResolve() throws ObjectStreamException { return INSTANCE; } }
懶漢式
延遲載入(使用時載入),節省記憶體
雙重判空,第一次判空防止重複加鎖,第二次判空才例項化
防止DCL指令重拍序,加volatile關鍵字
public class Singleton { private volatile static Singleton INSTANCE; //宣告成 volatile private Singleton (){} public static Singleton getSingleton() { if (INSTANCE == null) { synchronized (Singleton.class) { if (INSTANCE == null) { INSTANCE = new Singleton(); } } } return INSTANCE; } } //如果實現了Serializable, 必須重寫同上面餓漢式一樣的readResolve方法
列舉式
由JVM保證執行緒安全
序列化和反射攻擊已經被列舉解決
//enum列舉類 public enum Singleton { INSTANCE; public void yourMethod() { } }
內部類實現單例
當Singleton被載入時,其內部類並不會被初始化,故可以確保當 Singleton類被載入JVM時,不會初始化單例類。只有 getInstance() 方法呼叫時,才會初始化 instance。同時,由於例項的建立是時在類載入時完成,故天生對多執行緒友好,getInstance() 方法也無需使用同步關鍵字。
public class Singleton { /** * 類級的內部類,也就是靜態的成員式內部類,該內部類的例項與外部類的例項沒有繫結關係, * 而且只有被呼叫到才會裝載,從而實現了延遲載入 */ private static class SingletonHolder{ /** * 靜態初始化器,由JVM來保證執行緒安全 */ private static final Singleton instance = new Singleton(); } /** * 私有化構造方法 */ private Singleton(){ } public staticSingleton getInstance(){ return SingletonHolder.instance; } }