Singleton Pattern è probabilmente il design pattern più utilizzato. È uno schema semplice, facile da capire e da usare. A volte viene utilizzato in eccesso e in scenari in cui non è richiesto. In questi casi, gli svantaggi del suo utilizzo superano i vantaggi che comporta. Per questo motivo il modello singleton è talvolta considerato an antipattern o pattern singleton .
d infradito
Argomenti importanti per il modello di progettazione del metodo Singleton
- Che cos'è il modello di progettazione del metodo Singleton?
- Quando utilizzare il modello di progettazione del metodo Singleton?
- Tipi di inizializzazione di Singleton
- Componente chiave del modello di progettazione del metodo Singleton:
- Implementazione del modello di progettazione del metodo Singleton
- Diversi modi per implementare il modello di progettazione del metodo Singleton
- Caso d'uso del metodo Pattern Singleton
- Vantaggi del modello di progettazione del metodo Singleton:
- Svantaggi del modello di progettazione Singleton
1. Cos'è il modello di progettazione del metodo Singleton?
Il metodo Singleton o Singleton Design pattern è uno dei design pattern più semplici. Garantisce che una classe abbia una sola istanza e fornisce un punto di accesso globale ad essa.

2. Quando utilizzare il modello di progettazione del metodo Singleton?
Utilizzare il metodo Design Pattern Singleton quando:
- Deve esserci esattamente un'istanza di una classe e deve essere accessibile ai client da un punto di accesso noto.
- Quando l'unica istanza dovrebbe essere estensibile tramite sottoclassi e i client dovrebbero essere in grado di utilizzare un'istanza estesa senza modifiche
- Le classi singleton vengono utilizzate per la registrazione, gli oggetti driver, la memorizzazione nella cache, il pool di thread e le connessioni al database.
3. Tipi di inizializzazione di Singleton
La classe Singleton può essere istanziata con due metodi:
- Inizializzazione anticipata: In questo metodo, la classe viene inizializzata indipendentemente dal fatto che debba essere utilizzata o meno. Il vantaggio principale di questo metodo è la sua semplicità. Si avvia la lezione al momento del caricamento della lezione. Il suo svantaggio è che la classe viene sempre inizializzata indipendentemente dal fatto che venga utilizzata o meno.
- Inizializzazione pigra: In questo metodo, la classe viene inizializzata solo quando è richiesta. Può salvarti dal creare un'istanza della classe quando non ne hai bisogno. Generalmente, l'inizializzazione pigra viene utilizzata quando creiamo una classe singleton.
4. Componente chiave del modello di progettazione del metodo Singleton:
4.1. Membro statico:
Il modello Singleton o modello Singleton utilizza un membro statico all'interno della classe. Questo membro statico garantisce che la memoria venga allocata una sola volta, preservando la singola istanza della classe Singleton.
Giava
// Static member to hold the single instance private static Singleton instance;>
4.2. Costruttore privato:
Il pattern Singleton o pattern singleton incorpora un costruttore privato, che funge da barricata contro i tentativi esterni di creare istanze della classe Singleton. Ciò garantisce che la classe abbia il controllo sul proprio processo di istanziazione.
Giava // Private constructor to // prevent external instantiation class Singleton { // Making the constructor as Private private Singleton() { // Initialization code here } }>
4.3. Metodo di fabbrica statica:
Un aspetto cruciale del modello Singleton è la presenza di un metodo di fabbrica statica. Questo metodo funge da gateway, fornendo un punto di accesso globale all'oggetto Singleton. Quando qualcuno richiede un'istanza, questo metodo crea una nuova istanza (se non esiste) o restituisce l'istanza esistente al chiamante.
Giava // Static factory method for global access public static Singleton getInstance() { // Check if an instance exists if (instance == null) { // If no instance exists, create one instance = new Singleton(); } // Return the existing instance return instance; }>
5. Implementazione del modello di progettazione del metodo Singleton
L'implementazione di un Singleton Design Pattern o Pattern Singleton è descritta nel seguente diagramma di classi:

Implementazione del modello di progettazione del metodo Singleton
L'implementazione del Design pattern singleton è molto semplice e consiste in un'unica classe. Per garantire che l'istanza singleton sia unica, tutti i costruttori singleton dovrebbero essere resi privati. L'accesso globale viene effettuato tramite un metodo statico a cui è possibile accedere globalmente a una singola istanza, come mostrato nel codice.
Giava /*package whatever //do not write package name here */ import java.io.*; class Singleton { // static class private static Singleton instance; private Singleton() { System.out.println('Singleton is Instantiated.'); } public static Singleton getInstance() { if (instance == null) instance = new Singleton(); return instance; } public static void doSomething() { System.out.println('Somethong is Done.'); } } class GFG { public static void main(String[] args) { Singleton.getInstance().doSomething(); } }>
Produzione
Singleton is Instantiated. Somethong is Done.>
Il metodo getInstance, controlliamo se l'istanza è nulla. Se l'istanza non è nulla significa che l'oggetto è stato creato prima; altrimenti lo creeremo utilizzando l'operatore new.
6. Diversi modi per implementare il modello di progettazione del metodo Singleton
A volte è necessario avere una sola istanza della nostra classe, ad esempio una singola connessione DB condivisa da più oggetti, poiché la creazione di una connessione DB separata per ogni oggetto potrebbe essere costosa. Allo stesso modo, in un'applicazione può essere presente un singolo gestore di configurazione o di errori che gestisce tutti i problemi invece di creare più gestori.
es5 contro es6
Vediamo varie opzioni di progettazione per implementare tale classe. Se hai una buona padronanza delle variabili di classe statiche e dei modificatori di accesso, questo non dovrebbe essere un compito difficile.
Metodo 1 – Implementazione classica || Rendi getInstance() statico da implementare Modello di progettazione del metodo Singleton
Giava // Classical Java implementation of singleton // design pattern class Singleton { private static Singleton obj; // private constructor to force use of // getInstance() to create Singleton object private Singleton() {} public static Singleton getInstance() { if (obj == null) obj = new Singleton(); return obj; } }>
Qui abbiamo dichiarato getIstanza() static in modo che possiamo chiamarlo senza istanziare la classe. La prima volta getIstanza() si chiama crea un nuovo oggetto singleton e successivamente restituisce semplicemente lo stesso oggetto.
Nota: Singleton obj non viene creato finché non ne abbiamo bisogno e non chiamiamo il file getIstanza() metodo. Questa è chiamata istanziazione pigra. Il problema principale con il metodo sopra descritto è che non è thread-safe. Considera la seguente sequenza di esecuzione.
Questa sequenza di esecuzione crea due oggetti per il singleton. Pertanto questa implementazione classica non è thread-safe.
Metodo 2 || Rendi getInstance() sincronizzato per l'implementazione Modello di progettazione del metodo Singleton
Giava // Thread Synchronized Java implementation of // singleton design pattern class Singleton { private static Singleton obj; private Singleton() {} // Only one thread can execute this at a time public static synchronized Singleton getInstance() { if (obj == null) obj = new Singleton(); return obj; } }>
Qui l'utilizzo della sincronizzazione garantisce che possa essere eseguito solo un thread alla volta getIstanza() . Lo svantaggio principale di questo metodo è che l'utilizzo della sincronizzazione ogni volta durante la creazione dell'oggetto singleton è costoso e potrebbe ridurre le prestazioni del programma. Tuttavia, se le prestazioni di getIstanza() non è fondamentale per la tua applicazione, questo metodo fornisce una soluzione semplice e pulita.
Metodo 3 – Istanziazione desiderosa || Implementazione basata sull'inizializzatore statico del modello di progettazione singleton
Giava // Static initializer based Java implementation of // singleton design pattern class Singleton { private static Singleton obj = new Singleton(); private Singleton() {} public static Singleton getInstance() { return obj; } }>
Qui abbiamo creato un'istanza di un singleton in un inizializzatore statico. JVM esegue un inizializzatore statico quando la classe viene caricata e quindi è garantito che sia thread-safe. Utilizza questo metodo solo quando la classe singleton è leggera e viene utilizzata durante l'esecuzione del programma.
Metodo 4 – Il più efficiente || Utilizzare il Double Checked Locking per implementare il modello di progettazione singleton
Se notate attentamente una volta creato un oggetto la sincronizzazione non è più utile perché ora obj non sarà nullo e qualsiasi sequenza di operazioni porterà a risultati coerenti. Quindi acquisiremo il blocco su getInstance() solo una volta quando obj è null. In questo modo sincronizziamo solo il primo passaggio, proprio quello che vogliamo.
Giava // Double Checked Locking based Java implementation of // singleton design pattern class Singleton { private static volatile Singleton obj = null; private Singleton() {} public static Singleton getInstance() { if (obj == null) { // To make thread safe synchronized (Singleton.class) { // check again as multiple threads // can reach above step if (obj == null) obj = new Singleton(); } } return obj; } }>
Abbiamo dichiarato l'oggetto volatile che garantisce che più thread offrano correttamente la variabile obj quando viene inizializzata sull'istanza Singleton. Questo metodo riduce drasticamente il sovraccarico derivante dalla chiamata ogni volta del metodo sincronizzato.
7. Caso d'uso del metodo Pattern Singleton
- Connessioni al database: Nelle applicazioni in cui la creazione e la gestione delle connessioni al database è un'operazione costosa, è possibile utilizzare un Singleton per mantenere un'unica connessione al database in tutta l'applicazione.
- Gestione della configurazione: Quando si dispone di impostazioni di configurazione globali a cui è necessario accedere da vari componenti dell'applicazione, un gestore di configurazione Singleton può fornire un unico punto di accesso a queste impostazioni.
- Componenti della GUI: Per i componenti o i controller dell'interfaccia utente grafica (GUI), un Singleton può aiutare a gestire lo stato e le azioni dell'interfaccia utente, fornendo un unico punto di controllo.
- Gestori dispositivi: Nei sistemi o nelle applicazioni embedded che interagiscono con dispositivi hardware, un Singleton può essere utilizzato per gestire e controllare l'accesso ai dispositivi hardware per evitare conflitti.
- Servizio di stampa: Nei sistemi che prevedono la stampa di documenti o report, un servizio di stampa Singleton può coordinare e gestire i lavori di stampa, garantendo un utilizzo efficiente delle risorse di stampa.
8. Vantaggi del modello di progettazione del metodo Singleton:
- Risolve le collisioni di nomi: Negli scenari in cui è necessario un singolo punto di controllo per evitare conflitti o collisioni di denominazione, il modello Singleton garantisce che sia presente una sola istanza con un nome univoco.
- Inizializzazione desiderosa o pigra: Il modello Singleton supporta sia l'inizializzazione desiderosa (creando l'istanza quando la classe viene caricata) sia l'inizializzazione pigra (creando l'istanza quando viene richiesta per la prima volta), fornendo flessibilità in base al caso d'uso.
- Sicurezza del filo: I modelli Singleton implementati correttamente possono garantire la sicurezza del thread, garantendo che l'istanza venga creata in modo atomico e che più thread non creino inavvertitamente istanze duplicate.
- Impronta di memoria ridotta: Nelle applicazioni in cui il consumo di risorse è critico, il modello Singleton può contribuire a ridurre l'impronta di memoria garantendo che sia presente una sola istanza della classe.
9. Svantaggi del modello di progettazione singleton
- Difficoltà di test: Poiché i Singleton introducono lo stato globale, i test unitari possono diventare impegnativi. Testare un componente isolato può essere più complicato se si basa su un Singleton, poiché lo stato del Singleton può influenzare il risultato dei test.
- Problemi di concorrenza: In un ambiente multi-thread possono verificarsi problemi relativi alla creazione e all'inizializzazione dell'istanza Singleton. Se più thread tentano di creare Singleton contemporaneamente, possono verificarsi condizioni di competizione.
- Estendibilità limitata: Il modello Singleton può rendere il codice meno estensibile. Se in seguito decidi di aver bisogno di più istanze della classe o di voler modificare la logica di creazione di istanze, potrebbe essere necessario un refactoring significativo.
- Dipendenza globale: Il modello Singleton crea una dipendenza globale, rendendo più difficile sostituire il Singleton con un'implementazione alternativa o utilizzare l'inserimento delle dipendenze per fornire istanze.
- Difficile da sottoclassare: Sottoclassare un Singleton può essere impegnativo. Poiché il costruttore è in genere privato, l'estensione di un Singleton richiede ulteriore attenzione e potrebbe non seguire modelli di ereditarietà standard.
- Gestione del ciclo di vita: Il modello Singleton potrebbe non gestire scenari in cui l'istanza deve essere distrutta o reimpostata esplicitamente. La gestione del ciclo di vita del Singleton può diventare una preoccupazione.
- Abuso del punto di accesso globale: Sebbene un punto di accesso globale sia un vantaggio, può anche essere abusato. Gli sviluppatori potrebbero essere tentati di utilizzare Singleton per qualsiasi cosa, portando a un uso eccessivo dello stato globale e a un design meno modulare.
10. Conclusione
È importante che alcune classi abbiano esattamente un'istanza. Anche se in un sistema possono essere presenti molte stampanti, dovrebbe essere presente un solo spooler di stampa. Dovrebbe esserci un solo file system e un gestore di finestre. Un filtro digitale avrà un convertitore A/D. Un sistema contabile sarà dedicato al servizio di una società. Come possiamo garantire che una classe abbia una sola istanza e che l'istanza sia facilmente accessibile? Una variabile globale rende un oggetto accessibile, ma non ti impedisce di istanziare più oggetti.
Una soluzione migliore è rendere la classe stessa responsabile di tenere traccia della sua unica istanza. La classe può garantire che non possa essere creata nessun'altra istanza (intercettando le richieste per creare nuovi oggetti) e può fornire un modo per accedere all'istanza. Questo è il modello Singleton.