2012-10-02 17 views
14

Jaki jest właściwy sposób inicjowania singletona opartego na języku Java, jeśli muszę go zainicjować, zanim będę mógł użyć obiektu.Jak zainicjować Singleton oparty na enumie Java?

Zacząłem pisać kod, ale nie jestem pewien, czy robię to dobrze. Czy możesz mi pomóc w zaimplementowaniu tego singletonu dla mnie?

public enum BitCheck { 

    INSTANCE; 

    private static HashMap<String, String> props = null; 

    public synchronized void initialize(HashMap<String, String> properties) { 
     if(props == null) { 
      props = properties; 
     } 
    } 

    public boolean isAenabled(){ 
     return "Y".equalsIgnoreCase(props.get("A_ENABLED")); 
    } 

    public boolean isBenabled(){ 
     return "Y".equalsIgnoreCase(props.get("B_ENABLED")); 
    } 

} 
+0

Nie podoba mi się to, co próbujesz osiągnąć? – zengr

+0

Dlaczego potrzebujesz wyliczenia z jednym elementem, gdy używasz już singletonu? – Dunes

+0

@Dunes Chcę singleton, aby móc go używać w całej mojej bazie kodu w celu sprawdzenia wartości. Zainicjuję właściwości podczas uruchamiania i użyję metod sprawdzania w całym projekcie. –

Odpowiedz

30

Jest to całkiem możliwe, aby utworzyć konstruktor dla enum:

public enum BitCheck { 

    INSTANCE; 

    BitCheck() { 
     props = new HashMap<String, String>(); 
    } 

    private final Map<String, String> props; 

    //.. 

} 

zauważyć, że:

  • props pole może być ostateczna (lubimy final)
  • props nie ma być static
  • konstruktor nazywa się automatycznie i chętnie do ciebie

Przestrzegać ostatniego punktu. Ponieważ enum -singletons są tworzone chętnie po załadowaniu klasy enum BitCheck, nie masz możliwości przekazania żadnych argumentów do konstruktora. Oczywiście mogą Cię przez INSTANCE deklarację:

public enum BitCheck { 

    INSTANCE(new HashMap<String, String>()); 

    BitCheck(final Map<String, String> props) { 
     this.props = props; 
    } 

ale to nie robi żadnej różnicy, prawda? Co chcesz osiągnąć? Może potrzebujesz leniwego inicjowanego singletonu?

+0

Myślę, że będzie to zły pomysł, aby stworzyć tak, ponieważ konstruktor nie oferuje niczego dobrego. Może to być prosta deklaracja. –

+0

Chcę zainicjować przy użyciu zestawu wartości, które chcę przekazać do singletonu. Jak mogę to zrobić? Twój przykład uruchamia się z pustą hashmapą. –

+1

@java_mouse: o to chodzi. Nie ma sposobu, aby cokolwiek przekazać konstruktorowi z zewnątrz, 'enum' singleton nie pomoże ci. –

1
public enum BitCheck { 

    INSTANCE; 

    private BitCheck() { 
     // initialize here 
    } 

} 
5

Musisz tylko zainicjować go w deklaracji.

public enum BitCheck { 
    INSTANCE; 
    private final Map<String, String> props = new ConcurrentHashMap<String, String>(); 

    public void putAll(HashMap<String, String> map) { 
     props.putAll(map); 
    } 
} 
+0

+1, powinieneś zsynchronizować 'rekwizyty' w jakiś sposób. –

+0

Yup. Dzięki zmienili to. –

0

Możesz spróbować czegoś takiego w swoim kodzie singletowym opartym na zasadzie Enum. To sprawi, że Singleton będzie można zainicjować dokładnie jeden raz.

private static Properties props; 
private static AtomicBoolean isInitialized = new AtomicBoolean(false); 

public void init(Properties props){ 
    if(isInitialized.compareAndSet(false, true)) { 
     this.props = props; 
    } 
} 

UWAGA: W przypadku bardziej złożonych inicjalizacji, musisz 2 AtomicBooleans dla initStarted i initCompleted (zamiast pojedynczego AtomicBoolean - isInitialized). Następnie pierwszy wątek ustawia initStarted i wykonuje kroki inicjowania, reszta czeka, aż initCompleted zostanie ustawiona na wartość true przez pierwszy wątek.