venerdì 8 ottobre 2010

Singleton Design Pattern C#

Il Singleton è uno dei pattern fondamentali della programmazione ad oggetti e viene utilizzato quando si ha l'esigenza di creare una sola istanza per una determinata classe.
In pratica se vogliamo che nella nostra applicazione ci sia un solo oggetto di un determinato tipo la "Gang of four" consiglia di utilizzare il singleton come accesso "globale" a questa unica istanza.
I requisiti per implementare questo pattern sono i seguenti:
  1. Un singolo costruttore privato e senza parametri. Questo evita che altre classi possano istanziare nuovi oggetti del tipo in questione (sarebbe una violazione del pattern) 
  2.  La presenza di una variabile statica (variabile di classe) che mantiene il riferimento all'unica istanza possibile
  3. Un metodo pubblico e statico che permette alle altre classi di accedere alla variabile del punto 2 e inizializzarla se ancora non creata.
Vediamo una semplice realizzazione in C#

public sealed class Singleton
{
    private static Singleton _instance = null;

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (_instance==null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }
    }
}

La proprietà Instance verifica se la variabile _instance è stata già inizializzata. In caso negativo provvede alla sua inizializzazione (new Singleton()). In ogni caso viene restituito il reiferimento stesso.
In questa maniera se siamo i primi a richiedere l'oggetto Singleton (Singleton.Instance) la classe inizializza l'oggetto e ce ne restituisce il riferimento. In caso contrario ci restituirà sempre il riferimento dell'unico oggetto presente.
In realtà il codice appena mostrato non considera l'eventualità che due threads si trovino contemporaneamente a dover valutare la condizione (_instance == null). In questo caso se dovessero verificare che l'oggetto non è stato inizializzato andrebbero a creare due istanze violando palesemente il pattern. In un contesto multi-threading il codice precedente non è sicuro e deve essere modificato ad esempio in questo modo:

public sealed class Singleton
{
    private static Singleton _instance=null;
    private static readonly object _padlock = new object();

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (_padlock)
            {
                if (_instance==null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
    }
}

L'introduzione di un lucchetto ci mette al riparo dalla possibilità che due thread valutino contemporaneamente la condizione di inizializzazione.

1 commento:

Davide Taddei ha detto...

Anche nel core di Joomla! è presente il design pattern SINGLETON. In questo articolo: Joomla! personalizzare il redirect dell'utente

Posta un commento