2011-04-20 60 views
5
public enum YourSingleton { 
    INSTANCE; 

    public void doStuff(String stuff) { 
     System.out.println("Doing " + stuff); 
    } 
} 

YourSingleton.INSTANCE.doStuff("some stuff"); 

這裏是原始鏈接, http://electrotek.wordpress.com/2008/08/06/singleton-in-java-the-proper-way/辛格爾頓 - 有道

我問爲什麼,我們可以調用函數doStuff這種方式在Java中。

+0

我發現從josefx一個很好的註釋通過這個環節http://stackoverflow.com/questions/2080681/difference-of-enum-between-java-and-c – q0987 2011-04-20 19:25:11

+0

參見[項目3:強制的具有私有構造函數或枚舉類型的Singleton屬性](http://drdobbs.com/java/208403883?pgno=3) – trashgod 2011-04-20 21:07:57

回答

5

在Java中,enum可以做所有class可以[1]YourSingleton.INSTANCE創建YourSingleton的實例,因此您可以調用方法,就好像它是一個常規的class實例,它基本上是。

看到官方的Java文檔對枚舉類型進行更深入的討論:http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

[1]enum沒有繼承的實際執行情況。由於所有enum類型的隱含繼承了java.lang.Enum,並且Java不支持多繼承,所以不能擴展任何其他內容。

+0

@ Travis-Webb YourSingleton.INSTANCE每次引用都創建一個新實例?因爲在那種情況下不是一個單身人士。我覺得我不清楚這是如何工作的 – Dave 2011-04-20 19:22:33

+0

@Dave,請檢查這個http://stackoverflow.com/questions/2080681/difference-of-enum-between-java-and-c – q0987 2011-04-20 19:24:40

+0

@Dave否,所有枚舉值在後臺是「靜態最終」。 – pickypg 2011-04-20 19:25:20

0

我知道這不是你要求的,但是當我需要一個班級作爲單身人士時,這可能會有所幫助。我創建了一個靜態getInstance方法,該方法創建並返回該類的新實例(如果不存在),或者返回其自身的現有引用,並且使該類的構造函數爲private。

例如:

public class NameOfClass{ 
    private static NameOfClass variableReferencingThisClass=new NameOfThisClass(); 

    private NameOfClass(){} 

    public static NameOfClass getInstance(){ 
     return variableReferencingThisClass; 
    } 
} 
+0

線程安全嗎? – 2011-04-20 19:27:04

+0

它不是線程安全的,並且在多線程應用程序中可能會導致創建和使用多個實例。在第一組使用後,它將「解決」成爲一個單身人士,但是如果任何人持有'getInstance()'返回的引用,那麼所有投注都關閉,並且這個「單身人士」永遠不會是單身人士或安全的使用。 – pickypg 2011-04-20 19:30:31

+0

我不這麼認爲。如果可能的話,編寫「private static final NameOfClass singleton = new NameOfClass()」,然後緩解getInstance()中的空檢查。但是本專題的其他文檔提到了「序列化和反思攻擊」,這是我從未想過的。 (雖然我認爲這個解決方案仍然留有一些時間可以運行多個構造函數。) – Marvo 2011-04-20 19:32:45

2

以實現單的傳統方式是好的,但要保持其地位的真正單,它需要保護自己免受複雜的序列化和反射攻擊。這樣做的一般方法是通過使類實現Serializable,使所有實例字段爲Transient並實現readResolve方法。 (返回相同的單例實例)。

Enum Singleton模式提供了所有這些功能。但主要原因,我喜歡Enum變種是它的可讀性。據我所知,它以一種更簡潔的方式傳達了它比傳統的單身更加簡潔(你不必向新開發人員解釋,涉及序列化的所有變幻莫測,以及序列化如何破壞單身人士的保證,以及爲什麼你需要readResolve方法等等。)

+1

我曾經使用接口將常量拉入類中,並且對此行爲感到失望,因爲雖然它起作用,但它不是用於接口。可能會有人反對使用Enum來創建單身人士嗎?這是濫用枚舉嗎? – Marvo 2011-04-20 19:36:42

+1

這個答案直指問題的核心。如果你們中有人需要參考,請參閱Effective Java(Bloch),第3項。http://books.google.com/books?id=ka2VUBqHiWkC&pg=PA17 – 2011-04-20 19:40:10

+0

@Marvo,濫用枚舉的論點是主觀的,但根據對我來說,使用Enum for singleton不會破壞任何使用合約。 (與Interface的情況不同,它用於執行某些它沒有被設計的事情),而且它優於其他Singleton模式的優點(簡化Impl,簡潔性和可讀性)聞風而動。 – 2011-04-20 19:48:21

0

你也可以使用雙鎖單例創建。假設類爲MyObject,構造函數爲private,並聲明static字段instance爲空。但是,這並不能保證2個單例最終不會被創建,而是比單個檢查更接近線程安全的嘗試。

public static MyObject getInstance() 
{ 
    if (instance == null) 
    { 
    synchronized(MyObject.class) { 
     if (instance == null)   
     instance = new MyObject(); 
    } 
    } 
    return instance; 
} 
+0

這怎麼比'最後的私人靜態MyObject INSTANCE = createInstance(); public static MyObject getInstance(){return INSTANCE; }' – 2011-04-20 22:02:15