有兩種常見的方式來實現單例。 兩者都基於保持構造方法私有和導出公共靜態成員以提供對唯一實例訪問
第一種
// Singleton with public final field
public class Elvis {
// 賦初值 定義爲final屬性
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
第二種
// Singleton with static factory
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
// 公共成員爲靜態的工廠方法,限制實例的創建
public static Elvis getInstance() { return INSTANCE; }
public void leaveTheBuilding() { ... }
}
如果要想保證單例在序列化的情況下不被破壞,需要將字段聲明爲transient,並重寫readreslve方法:
// readResolve method to preserve singleton property
private Object readResolve() {
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE;
}
這兩種方式可以通過反射,直接調用私有構造的方式破壞掉。
第三種方法是聲明一個單一元素的枚舉類:
// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
枚舉類型,更簡潔,提供無償的序列化機制,並提供了防止多個實例化的堅固保證,但不滿足單例需要繼承其他類的應用場景。
當編寫一個工具類,提供一些靜態方法與字段,不想被實例化與繼承時,也可以將構造方法私有化,防止類被實例化