Il singleton è sicuro il design pattern più conosciuto e più facile da implementare, indipendentemente dal linguaggio di programmazione che si sta usando. Per creare una classe singleton basta seguire i seguenti tre step:
package com.devblog.designpatterns;
public class Demo {
private static Demo instance = null;
private Demo() {}
public static Demo getInstance() {
if (instance == null) {
instance = new Demo();
}
return instance;
}
}
Abbiamo creato il nostro singleton, adesso garantiamo che la classe Demo abbia una sola istanza all’interno del nostro progetto. Ma cosa succede se si lavora in ambiente multithreading
? Per come è strutturato il metodo getIstance() non garantisce, in ambiente multithreading, una sola istanza della classe singleton ovvero si dice che il metodo getInstance non è Thread-safe
. Infatti più thread possono accedervi, e per i primi thread, quando la variabile d’istanza non è inizializzata, più thread possono entrare nell’ if e creare più istanze della classe Demo.
Ci sono diversi modi per rendere il metodo getInstance() thread-safe io ve ne mostrerò tre, parlandovi anche dei pro e dei contro:
1. Creare l’istanza della variabile al tempo di caricamento della classe
private static final Demo instance = new Demo();
Pro:
Contro:
2. Aggiungere synchronized
al metodo getInstance()
Pro:
Contro:
3. Usare synchronized
nel blocco if e la variabile volatile
Pro:
Contro:
package com.devblog.designpatterns; public class Demo { private static volatile Demo instance; private Demo() { } public static Demo getInstance() { if (instance == null) { synchronized (Demo.class) { if (instance == null) instance = new Demo(); } } return instance; } }