☆ 作為對象的建立模式,單例模式確保某一個類只有一個執行個體,而且自行執行個體化並向整個系統提供這個執行個體,這個類稱為單例類。
§ 15.1 引言
☆ 一些資源管理員常常設計為單例模式,比如列印管理器、傳真管理器、通訊連接埠管理器或者一些管理內部資源如設定檔管理員等。
☆ Windows的資源回收筒是一個很好的單例的實際例子。
§ 15.2 單例模式的結構
☆ 單例模式的特點:
① 單例類只能有一個執行個體;
② 單例類必須自己建立自己的唯一執行個體;
③ 單例類必須給所有其他對象提供這一執行個體。
☆ 餓漢式單例類
public class EagerSingleton
...{
/** *//**
* 所謂餓漢式單例,就是直接在聲明處執行個體化自身執行個體
*/
private static final EagerSingleton _instance = new EagerSingleton() ;
/** *//**
* 私人建構函式,確保類不會被其他用戶端執行個體化。
*/
private EagerSingleton() ...{}
/** *//**
* 像整個應用提供唯一的執行個體。
*/
public static EagerSingleton getInstance()
...{
return _instance ;
}
}
☆ 懶漢式單例類
public class LazySingleton
...{
/** *//**
* 注意,懶漢式單例並沒有在聲明處執行個體化自身的執行個體。
*/
private static LazySingleton _instance = null ;
/** *//**
* 私人建構函式。
*/
private LazySingleton() ...{}
/** *//**
* 取得執行個體的方法,懶漢式單例在取得執行個體的方法裡面去執行個體化自身。
* 注意,該方法應加線程鎖,防止多線程環境下執行個體檢測混亂。
*/
synchronized public static LazySingleton getInstance()
...{
if( null == _instance )
_instance = new LazySingleton() ;
return _instance ;
}
}
§ 15.4 單例類的狀態
☆ 單例類中可以存在一些標識目前狀態的屬性,這個時候單例類就是有狀態的,反之就是無狀態的單例類。有狀態的單例類常常用來當作狀態庫使用。
有狀態的單例類實現起來要注意幾點,一是設計的時候要考慮到多線程修改狀態的問題,必要的地方加線程鎖;二是在如EJB這樣的多JVM技術架構,或者同一個JVM中有多個類載入器的情況下,盡量避免使用有狀態的單例實現。
無狀態的單例實現通常應該設計成不變類。
§ 15.5 Java語言中的單例模式
本節舉java.lang.Runtime例,說明jkd中的單例應用。
比較有用的就是用Runtime.getRuntime().exec()來執行外部命令。
§ 15.7 不完全單例類
public class LazySingleton
...{
/** *//**
* 注意,懶漢式單例並沒有在聲明處執行個體化自身的執行個體。
*/
private static LazySingleton _instance = null ;
/** *//**
* 公有的建構函式,可以直接執行個體化。
*/
public LazySingleton() ...{}
/** *//**
* 取得執行個體的方法,懶漢式單例在取得執行個體的方法裡面去執行個體化自身。
* 注意,該方法應加線程鎖,防止多線程環境下執行個體檢測失敗。
*/
synchronized public static LazySingleton getInstance()
...{
if( null == _instance )
_instance = new LazySingleton() ;
return _instance ;
}
}
也叫預設執行個體模式,使用者可以選擇自己產生執行個體,也可以選擇通過Factory 方法得到的共用執行個體。這樣等於把選擇執行個體化方式的責任交給用戶端,很難保證用戶端正確使用該類。不建議作出這樣的設計。
§ 15.8 相關模式
和單例模式關係最大的莫過於多例模式和簡單原廠模式,不多寫了。
☆ 最後一節以大量的篇幅說明“雙重檢測成例”在java下行不通,覺得有點無聊。
☆ 書中的登記式單例實現,怎麼看怎麼是個不完全單例,所以沒有細研究。不知道是GOF當初就這麼實現的還是讓這老仙給改成這樣的,有點亂七八糟。
☆ 總結一下,本章最有用的知識點:
一是單例的特點;
二是懶漢和餓漢兩種單例的實現,其中懶漢式單例要注意多線程問題;
三是有狀態單例嚴格禁止在分布式應用中使用;
四是不要作出所謂的“不完全單例”設計;
五是雙重檢查成例不要用java寫。