1.Singleton指僅僅被實例化一次的類。Singleton通常被用來代表那些本質上唯一的系統組件,如窗口管理器或者文件系統。使類稱為Singleton會使它的客戶端調試變的十分困難,因為無法給Singleton替換模擬實現,除非它實現一個充當其類型的接口.
2.在Java1.5發行版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有,并導出公有的靜態成員,以便客戶端能夠訪問該類的唯一實例,以便允許client能夠訪問該類的唯一實例。
3.第一種方法中,公有靜態成員是個final域:
public class Singleton1
{
public static final Singleton1 INSTANCE = new Singleton1();
//私有改造函數
private Singleton1()
{
}
//其他方法實現
public void otherMethod()
{
//...
}
}
私有構造器僅被調用一次,用來實例化公有的靜態final域Singleton1.INSTANCE.由于缺少公有的或者受保護的構造器,所以保證了Singleton1的全局唯一性。一旦其被實例化,只會存在一個實例,不多也不少。客戶端的任何行為都不會改變這一點。
注:享有特權的client可以借助AccessibleObject.setAccessible方法,通過反射機制調用私有構造器。如果要抵御這種攻擊,需要修改構造器,讓其在創建第二個實例的時候拋出異常。
4.在實現Singleton的第二種方法中,公有的成員是個靜態工廠方法:
public class Singleton2
{
//私有static Instance
private static final Singleton2 INSTANCE = new Singleton2();
//私有構造函數
private Singleton2()
{
}
//獲取單例方法
public static Singleton2 getInstance()
{
return INSTANCE;
}
//其他方法
public void otherMethod()
{
//...
}
}
對于靜態方法Singleton2.getInstance的所有調用,都會返回同一個對象引用,所以永遠不會創建其他的實例。
注:上述利用反射的提醒依然適用。
5.公有域方法的好處在于,組成類的成員的聲明很清楚的表明了這個類是一個Singleton(final),公有的靜態域是final的,所以該域將總是包含相同的對象引用。公有域方法在性能上不再有任何優勢:現在JVM實現幾乎都能都將靜態工廠方法的調用內聯化。
注:內聯:指函數在被調用的地方直接展開,編譯器在調用時不用像一般函數那樣,參數壓棧,返回時參數出棧以及資源釋放等,這樣提高了程序執行速度.
6.工廠方法的優勢在于,它提供了靈活性:在不改變其API的前提下,我們可以改變該類是否為Singleton的想法。工廠方法返回該類的唯一實例,不過它可以很容易被修改,如改成為每個調用該方法的線程返回一個唯一的實例。
第二個優勢在于與泛型有關。
這些優勢之間通常不相關,public域的方法比較簡單.
7.以上的兩種的其中一種方法實現的Singleton類如果變成是可序列化的Serialiazble,僅僅在聲明加上implements Serializable是不夠的。為了維護并保證Singleton,必須聲明所有實例都是瞬時transient的,并提供 一個readResolve方法。否則每次反序列化一個序列化的實例時,都會創建一個新的實例。即會導致一個假冒的對象。為了防止這種情況,需要在單例類中增加readResolve方法->
注:readResolve方法用來重新指定反序列化得到的對象.
private Object readResolve()
{
return INSTANCE;
}
8.從Java 1.5發行版本起,實現Singleton還有第三種方法。只需編寫一個包含單個元素的枚舉類型。
public Enum Singleton3
{
INSTANCE;
public void otherMethod()
{
}
}
這種方法在功能上與公有域方法相近,但是其更加簡潔,無償提供了序列化機制,絕對防止多次實例化,即使是面對復雜的序列化或者反射攻擊的時候。 雖然這種方法還沒有廣泛使用,但是單元素的枚舉類型已經成為實現Singleton的最佳方法。
注:用反射調用私有構造函數:報錯:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects.
ps:枚舉真心不錯.
部分源碼:
























































































































































