1. 程式人生 > >用私有構造器或者列舉型別強化Singleton屬性

用私有構造器或者列舉型別強化Singleton屬性

在java1.5版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有的,並匯出公有的靜態成員,一遍允許客戶端能夠訪問該類的唯一例項。在第一種方法中,公有靜態成員是個final域:

public class Elvis{
    public static final Elvis INSTANCE = new Elvis();
    private Elvis(){...}
    public void leaveTheBuilding(){...}
}

私有構造器僅被呼叫一次,用來例項化共有的靜態final域Elvis.INSTANCE。

在實現Singleton的第二種方法中,共有的成員是個靜態工廠方法:

public class Elvis{
    public static final Elvis INSTANCE = new Elvis();
    private Elvis(){...}
    public static Elvis getInstance(){return INSTANCE}
    public void leaveTheBuilding(){...}
}

對於靜態方法Elvis.getInstance的所有呼叫,都會返回同一個物件引用,所以,永遠不會建立其他的Elvis例項。
公有域的主要好處在於,組成類的成員的宣告很清楚的表明了這個類是一個Singleton:公有的靜態與是final的,所以該域將總是包含相同的物件引用。
在java1.5版本起,實現Singleton還有第三種方法。只需要編寫一個包含單元素的列舉型別:

public enum Elvis(){
    INSTANCE;
    public void leaveBuilding(){...}
}

這種方法在功能上與公有域方法相近,但是它更加簡潔,無償的提供了序列化機制,絕對防止多次例項化,即使是在面對複雜的序列化或者反射攻擊的時候,雖然這種方法還沒有廣泛採用,但是單元素的列舉型別已經成為Singleton的最佳方法。