一、背景
所謂的Singleton是指僅僅被實例化一次的類,Singleton通常被用來代表那些本質上唯一的系統組件。
實現Singleton有以下三種方法:
①. 私有構造器,公有靜態final域。
②. 私有構造器,公有靜態工廠方法。
③. 單元素枚舉類型(首選)。
二、私有構造器,公有靜態final域
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1(); // 公有靜態final域
/*
* 私有構造器
*/
private Singleton1() {
}
}
三、私有構造器,公有靜態工廠方法
缺點1:享有特權的客戶端可以借助AccessibleObject.setAccessible方法,通過反射機制,調用私有構造器,如果需要抵御這種攻擊,可以修改構造器,讓它在被要求創建第二個實例的時候拋出異常。
public class Singleton2 {
private static final Singleton2 INSTANCE = new Singleton2(); // 私有靜態final域
/*
* 私有構造器
*/
private Singleton2() {
}
/*
* 公有靜態工廠方法
*/
public static Singleton2 getInstance() {
return INSTANCE;
}
}
查看本欄目
缺點2:每次反序列化一個序列化的實例時,都會創建一個新的實例,為了防止這種情況,不僅要實現Serializable接口,還要提供一個readResolve方法。
public class Singleton2 implements Serializable {
private static final long serialVersionUID = 1L;
private static final Singleton2 INSTANCE = new Singleton2(); // 私有靜態final域
/*
* 私有構造器
*/
private Singleton2() {
}
/*
* 公有靜態工廠方法
*/
public static Singleton2 getInstance() {
return INSTANCE;
}
/*
* 反序列化確保只有一個實例
*/
public Object readResolve() {
return INSTANCE;
}
}
四、單元素枚舉類型
最佳方法:更簡潔,無償提供序列化機制,絕對防止多次實例化,即使是面對復雜的序列化或反射攻擊的時候。
public enum Singleton3 {
INSTANCE;
public void testSingleton() {
System.out.println("testSingleton");
}
public static void main(String[] args) {
Singleton3.INSTANCE.testSingleton();
}
}
作者:csdn博客 zdp072