定義:
確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。
單例模式的使用場景
確保某個類只有一個對象的場景,避免產生多個對象消耗過多的資源,或者某種類型的對象只應該有且只有一個。
單例模式UML類圖
角色介紹
1.Client-高層客戶端
2.Singleton-單例類
實現單例模式的幾個關鍵點
1.構造函數不對外開放(Private修飾符)
2.通過一個靜態方法或者枚舉返回單例類對象
3.確保單例類的對象有且只有一個,尤其是多線程環境下
4.確保單例類對象在反序列化時不會被重新構建對象
單例類的幾種實現方式(線程安全的)
1.餓漢式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
2.懶漢式
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.DCL(雙檢鎖)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
4.靜態內部類
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
5.枚舉類
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
對比圖
項目 | JDK限制 | 是否 Lazy 初始化 | 實現難度 |
---|---|---|---|
餓漢 | 無 | 否 | 易 |
懶漢 | 無 | 是 | 易 |
DCL | 1.5起 | 是 | 較複雜 |
靜態內部類 | 無 | 是 | 一般 |
枚舉 | 1.5起 | 否 | 易 |
Android源碼可參考
Context,LayoutInflater
總結
單例模式是運用頻率很高的模式,但是,由於在客戶端通常沒有高併發的情況,因此,選擇那種實現方式都不會有太大影響。即便如此,出於效率考慮,我們推薦使用DCL和靜態內部類的方式。
在Android中的優缺點:
優點:
1.在內存裏只有一個實例,減少了內存的開銷,尤其是頻繁的創建和銷燬實例,且創建和銷燬又無法優化,單例模式的優勢就非常明顯
2.避免對資源的多重佔用(比如寫文件操作)。
3.在應用啓動的時候產生一個單例永駐內存
4.可以設置全局的訪問點,優化和共享資源訪問,可以設計一個單例類來處理所有表的映射。
缺點:
1.沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。
2.單例對象如果持有Context,那麼很容易引發內存泄漏,此時需要注意傳遞給單例對象的Context最好是Application Context
結束語
下一節我們將Builder模式