啥是Singleton
Singleton指僅僅被實例化一次的類,通常被用來代表那些本質惟一的系統組件。Android中Editable、AccessibilityManager類還有數據庫創建時常采用這種模式。
實現方法
- 構造器私有化,導出共有的靜態成員,這個靜態成員是final域的。
public class Elvis{
public static final Elvis INSTANCE=new Elvis();
private Elvis(){...}
public void leaveTheBuilding(){...}
}
私有構造器只在實例化共有的靜態final域Elvis.INSTANCE時被調用一次。由于 只有私有的構造器,所以保證了Elvis的全局唯一性。
但是,有些時候通過反射機制調用私有構造器會打破這種唯一性,這時可以修改構造器,當被要求創建第二個實例時拋出異常。
公有域方法好處在于組成類的成員的聲明很清楚地表明了這個類是一個Singleton。但是現代的JVM實現幾乎都能將靜態工廠方法(見下)的調用內聯化,所以公有域方法在性能上不再有任何優勢。
2.和上面差不許多,不過公有的成員變味了靜態工廠方法。
public class Elvis{
private static final Elvis INSTANCE=new Elvis();
private Elvis(){...}
public static final Elvis getInstance() {
return INSTANCE;
}
public void leaveTheBuilding(){...}
}
對于所有getInstance的調用,都會返回同一個對象引用,所以永遠不會創建其他Elvis實例,當然反射除外。
工廠方法的優勢之一在于它可以在不改變其API的前提下,可以改變該類是否應該為Singleton。另外一個優勢與泛型有關,public域的方法比較簡單。
小總結
上面兩種方法要變成可序列化的(Serializable),僅僅加上implements Serializable是不夠的。還需聲明所有實例域都是瞬時(transient)的,并提供一個readResolve方法。否則每次反序列化都會創建一個新的實例。
3.編寫一個包含單個元素的枚舉類型
public enum Elvis{
INSTANCE;
public void leaveTheBuilding(){}
}
這種方法功能上與公有域相近,但更簡潔,無償提供了序列化機制,即使面對復雜的序列化或者反射攻擊時也能防止多次實例化。這個大概是實現Singleton最佳方法。