Modelul Singleton este probabil cel mai utilizat model de design. Este un model simplu, ușor de înțeles și de utilizat. Uneori este folosit in exces si in scenarii in care nu este necesar. În astfel de cazuri, dezavantajele utilizării acestuia depășesc avantajele pe care le aduce. Din acest motiv, modelul singleton este uneori considerat un antipattern sau model singleton .
șir de caractere java conține
Subiecte importante pentru modelul de proiectare a metodei Singleton
- Ce este modelul de design al metodei Singleton?
- Când să utilizați modelul de design al metodei Singleton?
- Tipuri de inițializare Singleton
- Componenta cheie a modelului de proiectare a metodei Singleton:
- Implementarea modelului de proiectare a metodei Singleton
- Diferite moduri de implementare a modelului de proiectare a metodei Singleton
- Cazul de utilizare al metodei Pattern Singleton
- Avantajele modelului de proiectare a metodei Singleton:
- Dezavantajele modelului de design Singleton
1. Ce este modelul de design al metodei Singleton?
Metoda Singleton sau modelul Singleton Design este unul dintre cele mai simple modele de design. Se asigură că o clasă are o singură instanță și oferă un punct global de acces la ea.

2. Când să utilizați modelul de design al metodei Singleton?
Utilizați metoda Singleton Design Pattern atunci când:
- Trebuie să existe exact o instanță a unei clase și trebuie să fie accesibilă clienților dintr-un punct de acces binecunoscut.
- Când singura instanță ar trebui să fie extensibilă prin subclasare și clienții ar trebui să poată utiliza o instanță extinsă fără modificare
- Clasele Singleton sunt utilizate pentru înregistrare, obiecte driver, stocare în cache și pool de fire, conexiuni la baze de date.
3. Tipuri de inițializare Singleton
Clasa Singleton poate fi instanțiată prin două metode:
- Inițializare timpurie: În această metodă, clasa este inițializată indiferent dacă urmează să fie utilizată sau nu. Principalul avantaj al acestei metode este simplitatea ei. Inițiați clasa în momentul încărcării clasei. Dezavantajul său este că clasa este întotdeauna inițializată indiferent dacă este folosită sau nu.
- Inițializare leneșă: În această metodă, clasa este inițializată numai atunci când este necesar. Vă poate salva de la instanțiarea clasei atunci când nu aveți nevoie de ea. În general, inițializarea leneșă este folosită atunci când creăm o clasă singleton.
4. Componenta cheie a modelului de proiectare a metodei Singleton:
4.1. Membru static:
Modelul sau modelul Singleton Singleton folosește un membru static în cadrul clasei. Acest membru static asigură că memoria este alocată o singură dată, păstrând instanța unică a clasei Singleton.
Java
// Static member to hold the single instance private static Singleton instance;>
4.2. Constructor privat:
Modelul Singleton sau modelul singleton încorporează un constructor privat, care servește drept baricade împotriva încercărilor externe de a crea instanțe ale clasei Singleton. Acest lucru asigură că clasa are controlul asupra procesului său de instanțiere.
Java // Private constructor to // prevent external instantiation class Singleton { // Making the constructor as Private private Singleton() { // Initialization code here } }>
4.3. Metoda statică din fabrică:
Un aspect crucial al modelului Singleton este prezența unei metode statice din fabrică. Această metodă acționează ca o poartă, oferind un punct global de acces la obiectul Singleton. Când cineva solicită o instanță, această metodă fie creează o instanță nouă (dacă nu există), fie returnează instanța existentă apelantului.
Java // 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. Implementarea modelului de proiectare a metodei Singleton
Implementarea unui model de design Singleton sau a unui model Singleton este descrisă în următoarea diagramă de clasă:

Implementarea modelului de proiectare a metodei Singleton
Implementarea modelului de design singleton este foarte simplă și constă dintr-o singură clasă. Pentru a vă asigura că instanța singleton este unică, toți constructorii singleton ar trebui să fie privați. Accesul global se face printr-o metodă statică care poate fi accesată global la o singură instanță, așa cum se arată în cod.
Java /*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(); } }>
Ieșire
Singleton is Instantiated. Somethong is Done.>
Metoda getInstance, verificăm dacă instanța este nulă. Dacă instanța nu este nulă, înseamnă că obiectul a fost creat înainte; altfel îl creăm folosind noul operator.
6. Diferite moduri de implementare a modelului de proiectare a metodei Singleton
Uneori trebuie să avem o singură instanță a clasei noastre, de exemplu o singură conexiune DB partajată de mai multe obiecte, deoarece crearea unei conexiuni DB separate pentru fiecare obiect poate fi costisitoare. În mod similar, poate exista un singur manager de configurație sau un manager de erori într-o aplicație care se ocupă de toate problemele în loc să creeze mai mulți manageri.
Să vedem diferite opțiuni de proiectare pentru implementarea unei astfel de clase. Dacă ai un bun control asupra variabilelor de clasă statică și modificatorilor de acces, aceasta nu ar trebui să fie o sarcină dificilă.
Metoda 1 – Implementarea clasică || Faceți getInstance() static pentru implementare Model de proiectare a metodei Singleton
Java // 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; } }>
Aici am declarat getInstance() static, astfel încât să-l putem numi fără a instanția clasa. Prima dată getInstance() se numește, creează un nou obiect singleton și, după aceea, returnează doar același obiect.
Notă: Singleton obj nu este creat până când nu avem nevoie de el și numim getInstance() metodă. Aceasta se numește instanțiere leneșă. Principala problemă cu metoda de mai sus este că nu este sigură pentru fire. Luați în considerare următoarea secvență de execuție.
Această secvență de execuție creează două obiecte pentru singleton. Prin urmare, această implementare clasică nu este sigură pentru fire.
Metoda 2 || Faceți getInstance() sincronizat pentru implementare Model de proiectare a metodei Singleton
Java // 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; } }>
Aici, folosirea sincronizate vă asigură că se poate executa doar un fir la un moment dat getInstance() . Principalul dezavantaj al acestei metode este că utilizarea sincronizată de fiecare dată în timpul creării obiectului singleton este costisitoare și poate scădea performanța programului dumneavoastră. Cu toate acestea, dacă performanța de getInstance() nu este critică pentru aplicația dvs. această metodă oferă o soluție curată și simplă.
Metoda 3 – Instanțierea dornică || Implementarea bazată pe inițializator static a modelului de design singleton
Java // 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; } }>
Aici am creat o instanță a unui singleton într-un inițializator static. JVM execută un inițializator static atunci când clasa este încărcată și, prin urmare, acesta este garantat pentru fire-safe. Utilizați această metodă numai atunci când clasa dvs. singleton este ușoară și este utilizată pe toată durata execuției programului.
Metoda 4 – Cel mai eficient || Utilizați blocarea dublu verificată pentru a implementa modelul de design singleton
Dacă observați cu atenție odată ce un obiect este creat, sincronizarea nu mai este utilă deoarece acum obj nu va fi nulă și orice succesiune de operații va duce la rezultate consistente. Deci vom obține blocarea pe getInstance() o singură dată când obj este nul. În acest fel, sincronizăm doar prima cale, exact ceea ce ne dorim.
Java // 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; } }>
Am declarat obj volatil care asigură că mai multe fire de execuție oferă corect variabila obj atunci când este inițializată la instanța Singleton. Această metodă reduce drastic costul general de apelare a metodei sincronizate de fiecare dată.
7. Cazul de utilizare al metodei Pattern Singleton
- Conexiuni la baza de date: În aplicațiile în care crearea și gestionarea conexiunilor la baze de date este o operațiune costisitoare, un Singleton poate fi utilizat pentru a menține o singură conexiune la bază de date în întreaga aplicație.
- Managementul configurației: Când aveți setări de configurare globale care trebuie accesate de diferite componente ale aplicației, un manager de configurare Singleton poate oferi un singur punct de acces la aceste setări.
- Componente GUI: Pentru componentele sau controlerele interfeței grafice cu utilizatorul (GUI), un Singleton poate ajuta la gestionarea stării și acțiunilor interfeței de utilizator, oferind un singur punct de control.
- Manageri de dispozitive: În sistemele încorporate sau aplicațiile care interacționează cu dispozitivele hardware, un Singleton poate fi utilizat pentru a gestiona și controla accesul la dispozitivele hardware pentru a evita conflictele.
- Serviciu de imprimare: În sistemele care implică tipărirea documentelor sau rapoartelor, un serviciu de imprimare Singleton poate coordona și gestiona lucrările de imprimare, asigurând utilizarea eficientă a resurselor de imprimare.
8. Avantajele modelului de proiectare a metodei Singleton:
- Rezolvă coliziunile de nume: În scenariile în care este necesar un singur punct de control pentru a evita conflictele de denumire sau coliziunile, modelul Singleton asigură că există o singură instanță cu un nume unic.
- Inițializare dornică sau leneșă: Modelul Singleton acceptă atât inițializarea nerăbdătoare (crearea instanței atunci când clasa este încărcată), cât și inițializarea leneșă (crearea instanței atunci când este solicitată prima dată), oferind flexibilitate în funcție de cazul de utilizare.
- Siguranța firului: Modelele Singleton implementate corect pot oferi siguranță pentru fire, asigurând că instanța este creată atomic și că mai multe fire de execuție nu creează din greșeală instanțe duplicate.
- Amprentă redusă de memorie: În aplicațiile în care consumul de resurse este critic, modelul Singleton poate contribui la o amprentă de memorie redusă, asigurându-se că există o singură instanță a clasei.
9. Dezavantajele modelului de design Singleton
- Dificultăți de testare: Deoarece Singleton-urile introduc starea globală, testarea unitară poate deveni o provocare. Testarea unei singure componente în mod izolat poate fi mai complicată dacă se bazează pe un Singleton, deoarece starea Singleton-ului poate afecta rezultatul testelor.
- Probleme de concurență: Într-un mediu cu mai multe fire, pot apărea probleme legate de crearea și inițializarea instanței Singleton. Dacă mai multe fire de execuție încearcă să creeze Singletonul simultan, poate duce la condiții de cursă.
- Extensibilitate limitată: Modelul Singleton poate face codul mai puțin extensibil. Dacă ulterior decideți că aveți nevoie de mai multe instanțe ale clasei sau doriți să schimbați logica de instanțiere, poate necesita o refactorizare semnificativă.
- Dependență globală: Modelul Singleton creează o dependență globală, ceea ce face mai dificilă înlocuirea Singleton-ului cu o implementare alternativă sau utilizarea injecției de dependență pentru furnizarea de instanțe.
- Greu de subclasat: Subclasarea unui Singleton poate fi o provocare. Deoarece constructorul este de obicei privat, extinderea unui Singleton necesită îngrijire suplimentară și este posibil să nu urmeze tiparele standard de moștenire.
- Managementul ciclului de viață: Este posibil ca modelul Singleton să nu se ocupe de scenarii în care instanța trebuie să fie distrusă sau resetată în mod explicit. Gestionarea ciclului de viață al singletonului poate deveni o preocupare.
- Abuzul punctului de acces global: Deși un punct de acces global este un avantaj, acesta poate fi și abuzat. Dezvoltatorii ar putea fi tentați să folosească Singleton-ul pentru orice, ceea ce duce la o suprautilizare a stării globale și la un design mai puțin modular.
10. Concluzie
Este important ca unele clase să aibă exact o singură instanță. Deși într-un sistem pot exista multe imprimante, ar trebui să existe un singur spooler de imprimantă. Ar trebui să existe un singur sistem de fișiere și un manager de ferestre. Un filtru digital va avea un convertor A/D. Un sistem contabil va fi dedicat deservirii unei singure companii. Cum ne asigurăm că o clasă are o singură instanță și că instanța este ușor accesibilă? O variabilă globală face un obiect accesibil, dar nu vă împiedică să instanțiați mai multe obiecte.
O soluție mai bună este de a face clasa însăși responsabilă pentru ținerea evidenței singurei ei instanțe. Clasa poate asigura că nicio altă instanță nu poate fi creată (prin interceptarea solicitărilor de a crea noi obiecte) și poate oferi o modalitate de a accesa instanța. Acesta este modelul Singleton.