logo

Patró de disseny del mètode Singleton

El patró Singleton és probablement el patró de disseny més utilitzat. És un patró senzill, fàcil d'entendre i d'utilitzar. De vegades s'utilitza en excés i en escenaris on no és necessari. En aquests casos, els inconvenients d'utilitzar-lo superen els avantatges que comporta. Per aquesta raó, el patró singleton de vegades es considera un antipatró o patró singleton .

Singleton-Mètode-Disseny-Patró



Temes importants per al patró de disseny del mètode Singleton

1. Què és el patró de disseny del mètode Singleton?

El mètode Singleton o el patró de disseny Singleton és un dels patrons de disseny més senzills. Assegura que una classe només té una instància i proporciona un punt global d'accés a ella.

2. Quan utilitzar el patró de disseny del mètode Singleton?

Utilitzeu el mètode Singleton Design Pattern quan:



declaració switch java
  • Hi ha d'haver exactament una instància d'una classe i ha de ser accessible per als clients des d'un punt d'accés conegut.
  • Quan l'única instància hauria de ser extensible mitjançant subclassificació i els clients haurien de poder utilitzar una instància estesa sense modificar-la
  • Les classes Singleton s'utilitzen per al registre, objectes del controlador, memòria cau i agrupació de fils, connexions de bases de dades.

3. Tipus d'inicialització de Singleton

La classe Singleton es pot instanciar mitjançant dos mètodes:

algorisme dfs
  • Inicialització primerenca: En aquest mètode, la classe s'inicialitza tant si s'ha d'utilitzar com si no. El principal avantatge d'aquest mètode és la seva senzillesa. Inicieu la classe en el moment de carregar la classe. El seu inconvenient és que la classe sempre s'inicialitza tant si s'està utilitzant com si no.
  • Inicialització mandrosa: En aquest mètode, la classe s'inicialitza només quan es requereix. Pot estalviar-vos d'instanciar la classe quan no la necessiteu. Generalment, la inicialització mandrosa s'utilitza quan creem una classe singleton.

4. Component clau del patró de disseny del mètode Singleton:

Component-clau del patró de disseny del mètode Singleton (1)

4.1. Membre estàtic:

El patró o patró Singleton Singleton empra un membre estàtic dins de la classe. Aquest membre estàtic assegura que la memòria només s'assigna una vegada, conservant la única instància de la classe Singleton.



Java
// Static member to hold the single instance private static Singleton instance;>

4.2. Constructor privat:

El patró Singleton o el patró singleton incorpora un constructor privat, que serveix com a barricada contra els intents externs de crear instàncies de la classe Singleton. Això garanteix que la classe tingui control sobre el seu procés d'instanciació.

Java
// Private constructor to // prevent external instantiation class Singleton {  // Making the constructor as Private  private Singleton()  {  // Initialization code here  } }>

4.3. Mètode de fàbrica estàtica:

Un aspecte crucial del patró Singleton és la presència d'un mètode de fàbrica estàtica. Aquest mètode actua com a passarel·la, proporcionant un punt d'accés global a l'objecte Singleton. Quan algú sol·licita una instància, aquest mètode crea una instància nova (si no n'hi ha cap) o retorna la instància existent a la persona que truca.

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. Implementació del patró de disseny del mètode Singleton

La implementació d'un Patró de disseny Singleton o Patró Singleton es descriu al diagrama de classes següent:

Captura de pantalla-2023-12-07-174635

Implementació del patró de disseny del mètode Singleton

com funciona un ordinador

La implementació del patró de disseny singleton és molt senzilla i consta d'una sola classe. Per garantir que la instància singleton sigui única, tots els constructors singleton haurien de ser privats. L'accés global es fa mitjançant un mètode estàtic al qual es pot accedir globalment a una única instància, tal com es mostra al codi.

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();  } }>

Sortida
Singleton is Instantiated. Somethong is Done.>

El mètode getInstance, comprovem si la instància és nul·la. Si la instància no és nul·la, vol dir que l'objecte s'ha creat abans; en cas contrari, el creem amb l'operador nou.

6. Diferents maneres d'implementar el patró de disseny del mètode Singleton

De vegades necessitem tenir només una instància de la nostra classe, per exemple, una única connexió de base de dades compartida per diversos objectes, ja que crear una connexió de base de dades separada per a cada objecte pot ser costós. De la mateixa manera, hi pot haver un únic gestor de configuració o gestor d'errors en una aplicació que gestioni tots els problemes en lloc de crear diversos gestors.

Clàssic-Implementació

Vegem diverses opcions de disseny per implementar aquesta classe. Si teniu un bon maneig de les variables de classe estàtiques i els modificadors d'accés, això no hauria de ser una tasca difícil.

diagrama uml java

Mètode 1 – Implementació clàssica || Feu que getInstance() sigui estàtic per implementar Patró de disseny del mètode 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;  } }>

Aquí ho hem declarat getInstance() static perquè puguem anomenar-lo sense crear una instancia de la classe. La primera vegada getInstance() s'anomena crea un nou objecte singleton i després d'això, només retorna el mateix objecte.

Nota: Singleton obj no es crea fins que el necessitem i cridem a getInstance() mètode. Això s'anomena instanciació mandrosa. El principal problema amb el mètode anterior és que no és segur per a fils. Considereu la següent seqüència d'execució.

Aquesta seqüència d'execució crea dos objectes per al singleton. Per tant, aquesta implementació clàssica no és segura per a fils.

Mètode 2 || Feu que getInstance() es sincronitzi per implementar Patró de disseny del mètode 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;  } }>

Aquí l'ús de sincronitzat assegura que només es pot executar un fil alhora getInstance() . El principal desavantatge d'aquest mètode és que utilitzar sincronitzat cada vegada que es crea l'objecte singleton és car i pot disminuir el rendiment del programa. Tanmateix, si el rendiment de getInstance() no és crític per a la vostra aplicació, aquest mètode proporciona una solució neta i senzilla.

Mètode 3 - Instanciació ansiosa || Implementació basada en l'inicialitzador estàtic del patró de disseny 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; } }>

Aquí hem creat una instància d'un singleton en un inicialitzador estàtic. JVM executa un inicialitzador estàtic quan es carrega la classe i, per tant, es garanteix que és segur per a fils. Utilitzeu aquest mètode només quan la vostra classe singleton sigui lleugera i s'utilitza durant l'execució del vostre programa.

Mètode 4: més eficient || Utilitzeu el bloqueig de doble verificació per implementar un patró de disseny singleton

Si observeu amb cura un cop creat un objecte, la sincronització ja no és útil perquè ara obj no serà nul i qualsevol seqüència d'operacions donarà resultats coherents. Per tant, només adquirirem el bloqueig a getInstance() una vegada quan l'obj sigui nul. D'aquesta manera només sincronitzem el primer camí, just el que volem.

índex de llista
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;  } }>

Hem declarat l'obj volàtil que garanteix que diversos fils ofereixen la variable obj correctament quan s'inicialitza a la instància Singleton. Aquest mètode redueix dràsticament la sobrecàrrega de trucar al mètode sincronitzat cada vegada.

7. Cas d'ús del mètode Pattern Singleton

  • Connexions a la base de dades: A les aplicacions on crear i gestionar connexions de base de dades és una operació costosa, es pot utilitzar un Singleton per mantenir una única connexió de base de dades a tota l'aplicació.
  • Gestió de la configuració: Quan teniu paràmetres de configuració globals als quals cal accedir per diversos components de l'aplicació, un gestor de configuració de Singleton pot proporcionar un únic punt d'accés a aquests paràmetres.
  • Components de la GUI: Per als components o controladors de la interfície gràfica d'usuari (GUI), un Singleton pot ajudar a gestionar l'estat i les accions de la interfície d'usuari, proporcionant un únic punt de control.
  • Gestors de dispositius: En sistemes incrustats o aplicacions que interactuen amb dispositius de maquinari, es pot utilitzar un Singleton per gestionar i controlar l'accés als dispositius de maquinari per evitar conflictes.
  • Servei d'impressió: En els sistemes que impliquen la impressió de documents o informes, un servei d'impressió Singleton pot coordinar i gestionar els treballs d'impressió, assegurant un ús eficient dels recursos d'impressió.

8. Avantatges del patró de disseny del mètode Singleton:

  • Resol les col·lisions de noms: En els escenaris en què es necessita un únic punt de control per evitar conflictes de noms o col·lisions, el patró Singleton garanteix que només hi hagi una instància amb un nom únic.
  • Inicialització ansiosa o mandrosa: El patró Singleton admet tant la inicialització amb ganes (creant la instància quan es carrega la classe) com la inicialització mandrosa (creant la instància quan es sol·licita per primera vegada), proporcionant flexibilitat en funció del cas d'ús.
  • Seguretat del fil: Els patrons Singleton implementats correctament poden proporcionar seguretat de fil, garantint que la instància es creï atòmicament i que diversos fils no creïn instàncies duplicades inadvertidament.
  • Reducció de la petjada de memòria: En aplicacions on el consum de recursos és crític, el patró Singleton pot contribuir a reduir l'empremta de memòria assegurant que només hi ha una instància de la classe.

9. Desavantatges del patró de disseny Singleton

  • Dificultats de la prova: Com que els Singleton introdueixen un estat global, les proves d'unitats poden arribar a ser un repte. Provar un component de manera aïllada pot ser més complicat si es basa en un Singleton, ja que l'estat del Singleton pot afectar el resultat de les proves.
  • Problemes de concurrència: En un entorn multiprocés, hi pot haver problemes relacionats amb la creació i la inicialització de la instància Singleton. Si diversos fils intenten crear el Singleton simultàniament, pot provocar condicions de carrera.
  • Extensibilitat limitada: El patró Singleton pot fer que el codi sigui menys extensible. Si més tard decidiu que necessiteu diverses instàncies de la classe o voleu canviar la lògica d'instanciació, pot ser que requereixi una refactorització important.
  • Dependència global: El patró Singleton crea una dependència global, cosa que fa més difícil substituir el Singleton per una implementació alternativa o utilitzar la injecció de dependència per proporcionar instàncies.
  • Difícil de subclassificar: Subclassificar un Singleton pot ser un repte. Com que el constructor és normalment privat, estendre un Singleton requereix una cura addicional i pot ser que no segueixi patrons d'herència estàndard.
  • Gestió del cicle de vida: El patró Singleton pot no gestionar escenaris en què la instància s'hagi de destruir o restablir explícitament. La gestió del cicle de vida del Singleton pot convertir-se en una preocupació.
  • Abús del punt d'accés global: Tot i que un punt d'accés global és un avantatge, també es pot abusar. Els desenvolupadors poden tenir la temptació d'utilitzar Singleton per a tot, la qual cosa comporta un ús excessiu de l'estat global i un disseny menys modular.

10. Conclusió

És important que algunes classes tinguin exactament una instància. Tot i que en un sistema hi pot haver moltes impressores, només hi hauria d'haver una col·locadora d'impressores. Només hi hauria d'haver un sistema de fitxers i un gestor de finestres. Un filtre digital tindrà un convertidor A/D. Es dedicarà un sistema de comptabilitat al servei d'una empresa. Com ens assegurem que una classe només té una instància i que la instància és fàcilment accessible? Una variable global fa que un objecte sigui accessible, però no us impedeix crear una instancia de diversos objectes.

Una millor solució és fer que la classe sigui responsable de fer un seguiment de la seva única instància. La classe pot garantir que no es pugui crear cap altra instància (interceptant sol·licituds per crear nous objectes) i pot proporcionar una manera d'accedir a la instància. Aquest és el patró Singleton.