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"));
}
}
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
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?
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);
}
}
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
public enum BitCheck {
INSTANCE;
private BitCheck() {
// initialize here
}
}
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.
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.