一、背景
所謂的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