2015-06-19 24 views
7

Próbuję utworzyć klasę singleton w Javie. Najlepsze dostępne rozwiązanie z wersją Java5 i nowszymi wydaje się używać enum. Ale nie jestem pewien, jak przekonwertować moją klasę do klasy singleton przy użyciu enum. Oto moja uproszczona klasa:Tworzenie pojedynczej klasy przy użyciu enum

public class Employee { 
    private int id; 
    private String name; 
    public Employee() {} 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
} 

Kiedy Szukałem odpowiedzi w internecie znalazłem następujący kod:

public enum EasySingleton{ 
    INSTANCE; 
} 

Ale gdzie są moje zmienne i metody klasy? Nie jestem pewien, jak to wdrożyć. Wiem, że możemy dostarczyć metody do enum, ale gdzie będą moje zmienne? Każda pomoc w tym zakresie byłaby naprawdę doceniana.

P.S .: Proszę nie debatować, jeśli singleton są złe lub anty-wzór. Jestem tylko ciekawy, jak utworzyć singleton przy użyciu enum.

+2

Wstawisz je do enum. Ale posiadanie * wymienialnej * enum byłoby bardzo dziwne - a posiadanie zmiennego singletonu byłoby również dziwne. "Pracownik" po prostu nie ma ochoty na naturalny singleton. –

+0

Zobacz [tutaj] (https://bitbucket.org/vadimvera/java-design-patterns/) i [tutaj] (https://bitbucket.org/vadimvera/java-standard-edition/src/d0ae9863354c48291cc4ff0e91e9f80fd96fdce2/ src/main/java/io/shido/patterns/Singleton.java? at = master) ... chociaż twoja klasa wygląda jak normalna klasa –

+0

Proszę odnieść się do tego: [post] (http://stackoverflow.com/a/2912312/2928710) –

Odpowiedz

11

Różnice między klasą a enumem nie są tak duże. Zmieniłem pierwszą linię kodu na public enum zamiast public class i dodałem nazwę twojej instancji.

public enum Employee { // changed "class" to "enum" 

    INSTANCE; // added name of the (single) instance 

    private int id; 
    private String name; 
    Employee() {} // removed "public" 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
} 

Proszę pamiętać, że singeltons przypadki enum, rzeczy statyczne może utrudniać Ci później, jeśli chcesz uruchomić swój kod kilka razy w jednym VM. Rozważ utworzenie instancji klasy Employee w głównej klasie i przekazanie jej za pośrednictwem aplikacji.

Poza tym, teksty stałe jakieś inne cechy szczególne:

  • Można dostępne są
  • konstruktorzy mogą być tylko nie extend innej klasy (tylko implements)
  • kilka predefiniowanych metod (jak static values() i getName()) pakiet prywatny lub prywatny
+0

Naprawdę nie rozumiem, dlaczego to powinien być problem, jeśli uruchomię mój kod kilka razy w jednej maszynie wirtualnej? Czy mógłbyś wyjaśnić trochę więcej, proszę. – gabriel

+0

Oczywiście, ale co właściwie masz na myśli, mówiąc: "uruchamiaj swój kod kilka razy w jednym vm"? – gabriel

+1

@gabriel Powiedzmy, że piszesz prostą grę tetris. W jednym polu gry używa jako klawiszy wejściowych "W, A, S, D". Teraz decydujesz, że chcesz, aby była to gra wieloosobowa - z dwoma polami gry, jeden użytkownik używa "W, A, S, D", a drugi użytkownik "I, J, K, L". Jeśli twój kod użył wielu "statycznych" zmiennych, trudno będzie "pozwolić, aby uruchomił się dwa razy" (raz dla każdego gracza). Ponowne użycie kodu jest znacznie łatwiejsze, jeśli unikniesz zmiennych statycznych. – slartidan

1
public enum SingletonEnum 
{ 
    INSTANCE; 

    public void doStuff() 
    { 
     System.out.println("Singleton using Enum"); 
    } 
} 

A ta może być wywołana z klientami:

public static void main(String[] args) 
{ 
    SingletonEnum.INSTANCE.doStuff(); 
} 
3

Twoja klasa „Pracownik” nie jest to coś, co powinno być pojedyncza, ale tu idzie.

public enum Employee { 
    INSTANCE; 

    private int id; 
    private String name; 

    private Employee() {} //enum constructor must be private 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

Następnie można zrobić

Employee.INSTANCE.setName("Hello World!"); 
1

(czy też nie Singleton jest dobrym rozwiązaniem dla Twojego przykład zastosowania jest omówione w innych odpowiedzi i komentarze. Będę udawać się odpowiedzieć na konkretne pytanie, nawet jeśli nie jest to istotne.)

Efektywna Java Blocha ma miłą dyskusję na ten temat. Patrz str. 17-18. Piszę bezpośrednio z tego źródła!

Zasadniczo można wymusić wzorzec singleton za pomocą wyliczenia lub prywatnego konstruktora. Bloch preferuje ten pierwszy, mimo że jest to mniej powszechny wzór.

np.:

// Enum singleton 
public enum Elvis { 
    INSTANCE; 
    public void leaveTheBuilding() { ... } 
} 

Funkcjonalność równoważna podejściu z pola publicznego i jest gotowa do serializacji bez żadnych dodatkowych elementów. I będzie tylko jeden przypadek, nawet w obliczu podstępnej refleksji lub dostępu do serializacji.

Powiązane problemy