Implementacja Singletona z Enum (w Javie)

Przeczytałem, że możliwe jest zaimplementowanie Singleton w Javie za pomocą Enum takiego jak:

public enum MySingleton {
     INSTANCE;   
}

Ale jak to działa? W szczególności należy utworzyć instancję Object. Jak powstaje MySingleton? Kto robi new MySingleton()?

Author: Elliott Frisch, 2014-10-09

6 answers

To,

public enum MySingleton {
  INSTANCE;   
}

Ma ukryty konstruktor pusty. Bądźmy wyraźni,

public enum MySingleton {
    INSTANCE;
    private MySingleton() {
        System.out.println("Here");
    }
}

Jeśli następnie dodałeś kolejną klasę z main() metodą jak

public static void main(String[] args) {
    System.out.println(MySingleton.INSTANCE);
}

Zobaczysz

Here
INSTANCE

enum pola są stałymi czasowymi kompilacji, ale są instancjami ich typu enum. I, są one konstruowane, gdy typ enum jest odwołany po raz pierwszy.

 167
Author: Elliott Frisch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-09 18:31:35

Typ enum jest specjalnym typem typu class.

Twoja enum deklaracja faktycznie kompiluje się do czegoś takiego jak

public final class MySingleton {
    public final static MySingleton INSTANCE = new MySingleton();
    private MySingleton(){} 
}

Kiedy twój kod uzyska pierwszy dostęp INSTANCE, klasa MySingleton zostanie załadowana i zainicjalizowana przez JVM. Proces ten inicjalizuje pole static powyżej raz (leniwie).

 55
Author: Sotirios Delimanolis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-11 18:01:28

W tej książce Joshua Bloch o najlepszych praktykach Javy, możesz znaleźć wyjaśnienie, dlaczego powinieneś egzekwować własność Singleton za pomocą prywatnego konstruktora lub typu Enum. Rozdział jest dość długi, więc streszczając go:

Tworzenie klasy A Singleton może utrudnić testowanie jej klientów, ponieważ niemożliwe jest zastąpienie wzorcowej implementacji singletonem, chyba że implementuje interfejs, który służy jako jej typ. Zalecanym podejściem jest wdrożenie singletonów przez po prostu tworzy Typ enum z jednym elementem:

// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}

To podejście jest funkcjonalnie równoważne z podejściem public field, z tą różnicą, że jest bardziej zwięzły, zapewnia maszynę serializacyjną za darmo i zapewnia żelazna gwarancja przed wieloma instancjami, nawet w obliczu wyrafinowanych ataki serializacyjne lub odbiciowe.

Choć podejście to nie jest jeszcze szeroko przyjęty, Jednoelementowy typ enum jest najlepszym sposobem implementacji singletonu.

 53
Author: ekostadinov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-10 06:08:50

Podobnie jak wszystkie instancje enum, Java tworzy instancje każdego obiektu po załadowaniu klasy, z pewnymi gwarancjami, że jest utworzona dokładnie raz na JVM . Pomyśl o deklaracji INSTANCE jako publicznym statycznym polu końcowym: Java utworzy instancję obiektu przy pierwszym odwołaniu do klasy.

Instancje są tworzone podczas inicjalizacji statycznej, która jest zdefiniowana w specyfikacji języka Java, sekcja 12.4.

Jeśli to coś warte, Joshua Bloch opisuje ten wzór szczegółowo jako punkt 3 Effective Java Second Edition .

 8
Author: Jeff Bowman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-08 22:21:45

Ponieważ Singleton Pattern polega na posiadaniu prywatnego konstruktora i wywołaniu jakiejś metody kontrolującej instancje (jak niektóre getInstance), W Enumach mamy już ukryty prywatny konstruktor.

Nie wiem dokładnie, jak JVM lub jakiś kontener kontroluje instancje naszego Enums, ale wygląda na to, że już używa implicit Singleton Pattern, Różnica polega na tym, że nie nazywamy getInstance, po prostu nazywamy Enum.

 3
Author: Bruno Franco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 07:02:07

Jak już wcześniej wspomniano, enum jest klasą Javy ze szczególnym warunkiem, że jej definicja musi zaczynać się od co najmniej jednej "stałej enum".

Część z tego, jest to klasa jak każda klasa i używasz jej, dodając metody poniżej definicji stałych:

public enum MySingleton {
    INSTANCE;

    public void doSomething() { ... }

    public synchronized String getSomething() { return something; }

    private String something;
}

Uzyskujesz dostęp do metod Singletona w następujący sposób:

MySingleton.INSTANCE.doSomething();
String something = MySingleton.INSTANCE.getSomething();

Użycie enum, zamiast klasy, jest, jak wspomniano w innych odpowiedziach, głównie o bezpiecznym wątku utworzenie singletonu i gwarancja, że zawsze będzie to tylko jedna kopia.

I, być może, najważniejsze, że takie zachowanie jest gwarantowane przez sam JVM i specyfikację Javy.

Oto sekcja ze specyfikacji Java na temat zapobiegania wielu instancjom instancji enum:

Typ enum nie ma instancji innych niż te zdefiniowane przez jego stałe enum. Jest to błąd w czasie kompilacji, aby próbować jawnie utworzyć instancję Typ enum. Ostateczna metoda klonowania w Enum zapewnia, że stałe enum nigdy nie mogą być klonowane, a specjalne traktowanie przez mechanizm serializacji zapewnia, że duplikaty instancji nigdy nie są tworzone w wyniku deserializacji. Zabronione jest tworzenie refleksyjnych instancji typów enum. Razem te cztery rzeczy zapewniają, że żadne instancje typu enum nie istnieją poza tymi zdefiniowanymi przez stałe enum.

Warto zauważyć, że po uruchomieniu wątku wszelkie obawy dotyczące bezpieczeństwa musi być traktowany jak w każdej innej klasie ze słowem kluczowym zsynchronizowanym itd.

 0
Author: Erk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-06 07:22:31