Singleton一般被用來表明那些本質上惟一的系統組件,在JDK1.5以前,實現Singleton有兩種方法。這兩種方法都要把構造器保持爲私有的,並導出公有的靜態成員,以便容許客戶端可以訪問該類的惟一實現。java
第一種方式:1.構造器私有,2,有一個公共的靜態成員,而且是final的。多線程
public class Singleton { private Singleton(){ //在此將構造函數設置爲private,防止該類在外部被實例化 } public static final Singleton Instance = new Singleton(); public void test(){ System.out.println("Test..."); } }
構造方法私有化的做用:外面調用只能調用類的靜態函數,而不能new去建立對象;私有構造函數只能在函數內部調用,外部不能實例化,因此私有構造函數能夠防止該類在外部被實例化。不過享有特v權的客戶端能夠藉助AccessibleObject.setAccessible()方法,經過反射機制調用私有構造器。若是須要抵禦這種攻擊,能夠修改構造器,讓他在被要求建立的第二個實例時候拋出異常。 函數
第二種方式:1,構造器私有,2,有一個私有的靜態成員,可是有一個公共的靜態工廠方法 spa
public class Singleton1 { private static final Singleton1 INSTANCE = new Singleton1(); private Singleton1(){} public static Singleton1 getInstance(){ return INSTANCE; } public void test(){ System.out.println("Test..."); } }
這就是傳說中的懶漢式的單例模式,通常狀況下,爲了防止多線程的時候建立多個實例,都會加上synchronized 關鍵字。線程
對於靜態方法getInstance()方法的全部調用,都會返回同一個對象的應用。這種寫法的好處是很清楚地代表了該類是一個Singleton,可是這種寫法有另外一個好處是,能夠添加其餘的靜態工廠方法返回另外一個新的實例,這樣就能夠將該類變爲非Signleton。爲了使利用上述方法實現Singleton類變成是可序列化的,僅僅在聲明時加上「implements Serializable」是不夠的。爲了維護並保證Singleton,必須聲明全部實例都是瞬時transient的,並提供 一個readResolve方法。不然每次反序列化一個序列化的實例時,都會建立一個新的實例。即會致使一個假冒的對象。爲了防止這種狀況,須要在單例類中增長readResolve方法。延伸以下:code
public class Singleton implements Serializable { public static final Singleton INSTANCE = new Singleton(); private Singleton() { } private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator. return INSTANCE; } }
實現Singleton還有第三種方法,從JDK1.5開始,只需編寫一個包含單個元素的枚舉類型。推薦的寫法:對象
public enum Singleton3 { INSTANCE; public void test(){ System.out.println("test..."); } }
這種方法在功能上與公有域接近,可是它更簡潔。雖然這種方法尚未普遍採用,可是單元素的枚舉類型已經成爲實現Singleton的最佳方法。get