Singleton
Da Wikipedia, l'enciclopedia libera.
Nella programmazione ad oggetti, il Singleton è uno dei pattern fondamentali, definiti originariamente dalla gang of four.
Il Singleton è un design pattern creazionale, il suo scopo è assicurare che una classe abbia una sola istanza e fornire un punto di accesso globale a tale istanza.
[modifica] Implementazione
Il metodo più semplice per implementare questo pattern è quello di rendere privato il costruttore della classe impedendone così l'istanziazione diretta, e nello stesso tempo fornire un metodo getter statico che restituisca ogni volta la stessa, unica, istanza. Eccone un esempio in codice Java:
public class MioSingolo { private static MioSingolo istanza = null; private MioSingolo() {} public static MioSingolo getMioSingolo() { if (istanza == null) { istanza = new MioSingolo(); } return istanza; } }
Ed ecco un esempio in codice C++:
#include <iostream> #define null 0 class singleton { private: static singleton* instance_ptr_; singleton() { }; public: ~singleton() { }; static singleton* get_instance() { if (instance_ptr_ == null) { instance_ptr_ = new singleton; } return instance_ptr_; } bool method() { return true; }; }; // initialize pointer singleton* singleton::instance_ptr_ = null; int main() { std::cout << singleton::get_instance()->method() << std::endl; return 0; }
In applicazioni multi-thread l'utilizzo di questo pattern richiede un'attenzione particolare: se due thread tentano di eseguire contemporaneamente il costruttore quando la classe non è stata ancora istanziata, devono entrambi controllare se l'istanza esiste e soltanto uno deve creare la nuova istanza. Ecco un'esempio di implementazione Thread-Safe in codice Java:
public class MioSingolo{ private static MioSingolo istanza = null; private MioSingolo() {} public static MioSingolo getMioSingolo() { synchronized (MioSingolo.class) { //equivalente a usare l'intero metodo synchronized if (istanza == null) { istanza = new MioSingolo(); } return istanza; } } }
Ed eccone la traduzione in codice C sharp. Questa implementazione è Thread-Safe, anche se l'utilizzo del lock sull'oggetto che funge da semaforo ne rallenta la velocità:
public class Singleton { private static Singleton istanza=null; private static object semaforo = new object(); private Singleton() {} public static Singleton Istanza { get { lock(semaforo) { if(istanza==null) istanza=new Singleton(); return istanza; } } } }
Affinché l'esempio non sia fuorviante è da notare che le implementazioni mostrate usano la lazy initialization ovvero creano l'oggetto solo quando viene effettivamente utilizzato. Esistono delle strategie diverse da questa.