web-dev-qa-db-fra.com

Comment initialiser Singleton basé sur Java enum?

Quelle est la bonne façon d’initialiser un singleton basé sur une énumération Java, si je dois l’initialiser avant de pouvoir utiliser l’objet.

J'ai commencé à écrire le code, mais je ne suis pas sûr de bien le faire. Pourriez-vous m'aider à mettre en œuvre ce singleton correct pour moi?

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"));
    }

}
15
java_mouse

Il est parfaitement possible de créer un constructeur pour enum:

public enum BitCheck {

    INSTANCE;

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

    private final Map<String, String> props;

    //..

}

Notez que:

  • props field peut être final (nous aimons final)
  • props ne doit pas nécessairement être static
  • constructeur est appelé automatiquement et avec impatience pour vous

Faites attention au dernier point. Puisque enum- singletons est créé avec impatience lorsque la classe enum BitCheck est chargée, vous ne pouvez transmettre aucun argument au constructeur. Bien sûr, vous pouvez utiliser la déclaration INSTANCE:

public enum BitCheck {

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

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

mais cela ne fait aucune différence, non? Que veux-tu accomplir? Peut-être avez-vous réellement besoin d'un singleton initialisé paresseux?

31

Vous devez simplement l'initialiser dans la déclaration.

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

    public void putAll(HashMap<String, String> map) {
        props.putAll(map);
    }
}
5
Amit Deshpande

Vous devez définir un constructeur comme ceci:

public enum BitCheck {

    INSTANCE;
    private final HashMap<String, String> props;

    BitCheck() {

    }
}

Planet enum est un très bon exemple à l'adresse: http://docs.Oracle.com/javase/tutorial/Java/javaOO/enum.html

2
Jordan Denison
public enum BitCheck {

    INSTANCE;

    private BitCheck() {
        // initialize here
    }

}
1
devang

Vous devez implémenter les interfaces et donc changer pour:

private Map<...> props;

Vous pouvez regarder Quelle est la meilleure approche pour utiliser un Enum en tant que singleton en Java? qui est semblable à ce que vous voulez.

1
ramsinb

Vous pouvez essayer quelque chose comme ceci dans votre code singleton basé sur Enum. Cela garantira que le Singleton peut être initialisé exactement une fois.

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

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

REMARQUE: pour une initialisation plus complexe, vous auriez besoin de 2 AtomicBooleans pour initStarted et initCompleted (au lieu d'un seul AtomicBoolean - isInitialized). Ensuite, le premier thread définit initStarted et exécute les étapes d'initialisation. Le reste attend jusqu'à ce que initCompleted soit défini sur true par le premier thread.

0
janeshs