logo

Singleton metode design mønster

Singleton Pattern er nok det mest udbredte designmønster. Det er et simpelt mønster, let at forstå og at bruge. Nogle gange bruges det i overkant og i scenarier, hvor det ikke er påkrævet. I sådanne tilfælde opvejer ulemperne ved at bruge det de fordele, det medfører. Af denne grund betragtes singleton-mønsteret nogle gange som et antimønster eller mønster singleton .

Singleton-Metode-Design-Mønster



Vigtige emner for Singleton Method Design Pattern

1. Hvad er Singleton Method Design Pattern?

Singleton-metoden eller Singleton Design-mønsteret er et af de enkleste designmønstre. Det sikrer, at en klasse kun har én instans og giver et globalt adgangspunkt til den.

streng sammenlignet

2. Hvornår skal man bruge Singleton Method Design Pattern?

Brug Singleton-metoden Design Pattern, når:



  • Der skal være præcis én forekomst af en klasse, og den skal være tilgængelig for klienter fra et velkendt adgangspunkt.
  • Når den eneste instans skal kunne udvides ved underklassificering og klienter skal kunne bruge en udvidet instans uden at ændre
  • Singleton-klasser bruges til logning, driverobjekter, caching og trådpulje, databaseforbindelser.

3. Initialiseringstyper af Singleton

Singleton-klassen kan instansieres ved to metoder:

  • Tidlig initialisering: I denne metode initialiseres klasse uanset om den skal bruges eller ej. Den største fordel ved denne metode er dens enkelhed. Du starter klassen på tidspunktet for klassens indlæsning. Dens ulempe er, at klassen altid initialiseres, uanset om den bruges eller ej.
  • Lazy initialisering: I denne metode initialiseres klasse kun, når det er påkrævet. Det kan redde dig fra at instansiere klassen, når du ikke har brug for det. Generelt bruges doven initialisering, når vi opretter en singleton-klasse.

4. Nøglekomponent i Singleton-metodens designmønster:

Key-Component-of-Singleton-Method-Design-Pattern-(1)

4.1. Statisk medlem:

Singleton-mønsteret eller -mønsteret Singleton anvender et statisk medlem i klassen. Dette statiske medlem sikrer, at hukommelsen kun tildeles én gang, hvilket bevarer den enkelte forekomst af Singleton-klassen.



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

4.2. Privat konstruktør:

Singleton-mønsteret eller mønster-singletonet inkorporerer en privat konstruktør, som fungerer som en barrikade mod eksterne forsøg på at skabe forekomster af Singleton-klassen. Dette sikrer, at klassen har kontrol over sin instansieringsproces.

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

4.3. Statisk fabriksmetode:

Et afgørende aspekt af Singleton-mønsteret er tilstedeværelsen af ​​en statisk fabriksmetode. Denne metode fungerer som en gateway, der giver et globalt adgangspunkt til Singleton-objektet. Når nogen anmoder om en instans, opretter denne metode enten en ny instans (hvis ingen eksisterer) eller returnerer den eksisterende instans til den der ringer.

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. Implementering af Singleton Method Design Pattern

Implementeringen af ​​et Singleton Design Pattern eller Pattern Singleton er beskrevet i følgende klassediagram:

Skærmbillede-2023-12-07-174635

Implementering af Singleton Method Design Pattern

Implementeringen af ​​singleton Design-mønsteret er meget enkel og består af en enkelt klasse. For at sikre, at singleton-instansen er unik, bør alle singleton-konstruktørerne gøres private. Global adgang sker gennem en statisk metode, der globalt kan få adgang til en enkelt instans som vist i koden.

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

Produktion
Singleton is Instantiated. Somethong is Done.>

GetInstance-metoden, vi tjekker om instansen er null. Hvis instansen ikke er null, betyder det, at objektet blev oprettet før; ellers opretter vi det med den nye operator.

6. Forskellige måder at implementere Singleton Method Design Pattern

Nogle gange skal vi kun have én forekomst af vores klasse, for eksempel en enkelt DB-forbindelse, der deles af flere objekter, da det kan være dyrt at oprette en separat DB-forbindelse for hvert objekt. På samme måde kan der være en enkelt konfigurationsmanager eller fejlmanager i en applikation, der håndterer alle problemer i stedet for at oprette flere managers.

Klassisk-implementering

Lad os se forskellige designmuligheder for at implementere en sådan klasse. Hvis du har et godt styr på statiske klassevariabler og adgangsmodifikatorer, burde dette ikke være en vanskelig opgave.

Metode 1 – Klassisk implementering || Gør getInstance() statisk for at implementere Singleton metode design mønster

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

Her har vi erklæret getInstance() statisk, så vi kan kalde det uden at instantiere klassen. Den første gang getInstance() kaldes det opretter et nyt singleton objekt og derefter returnerer det bare det samme objekt.

Bemærk: Singleton obj oprettes ikke før vi har brug for det og kalder det getInstance() metode. Dette kaldes doven instansiering. Hovedproblemet med ovenstående metode er, at den ikke er trådsikker. Overvej følgende udførelsessekvens.

Denne udførelsessekvens opretter to objekter til singletonen. Derfor er denne klassiske implementering ikke trådsikker.

Metode 2 || Gør getInstance() synkroniseret for at implementere Singleton metode design mønster

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

Her sikrer brug af synkroniseret, at kun én tråd ad gangen kan udføres getInstance() . Den største ulempe ved denne metode er, at det er dyrt at bruge synkroniseret hver gang, mens du opretter singleton-objektet, og kan reducere dit programs ydeevne. Men hvis udførelsen af getInstance() er ikke kritisk for din applikation, denne metode giver en ren og enkel løsning.

Metode 3 – Ivrig instansiering || Statisk initialiseringsbaseret implementering af singleton-designmønster

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

Her har vi lavet en instans af en singleton i en statisk initializer. JVM udfører en statisk initialisering, når klassen er indlæst, og derfor er denne garanteret trådsikker. Brug kun denne metode, når din singleton-klasse er let og bruges gennem hele programmets udførelse.

java liste metoder

Metode 4 – Mest effektiv || Brug Double Checked Locking til at implementere singleton designmønster

Hvis du omhyggeligt bemærker, når et objekt er oprettet, er synkronisering ikke længere nyttig, fordi nu vil obj ikke være null, og enhver sekvens af operationer vil føre til konsistente resultater. Så vi får kun låsen på getInstance() én gang, når obj er null. På denne måde synkroniserer vi kun den første vej igennem, lige hvad vi ønsker.

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

Vi har erklæret obj flygtige som sikrer, at flere tråde tilbyder obj-variablen korrekt, når den initialiseres til Singleton-forekomsten. Denne metode reducerer drastisk omkostningerne ved at kalde den synkroniserede metode hver gang.

7. Brug Case of Pattern Singleton Method

  • Databaseforbindelser: I applikationer, hvor oprettelse og styring af databaseforbindelser er en dyr operation, kan en Singleton bruges til at opretholde en enkelt databaseforbindelse i hele applikationen.
  • Konfigurationsstyring: Når du har globale konfigurationsindstillinger, der skal tilgås af forskellige komponenter i applikationen, kan en Singleton-konfigurationsadministrator give et enkelt adgangspunkt til disse indstillinger.
  • GUI-komponenter: For komponenter eller controllere til grafisk brugergrænseflade (GUI) kan en Singleton hjælpe med at administrere UI'ens tilstand og handlinger, hvilket giver et enkelt kontrolpunkt.
  • Enhedsadministratorer: I indlejrede systemer eller applikationer, der interagerer med hardwareenheder, kan en Singleton bruges til at administrere og kontrollere adgangen til hardwareenheder for at undgå konflikter.
  • Udskrivningsservice: I systemer, der involverer udskrivning af dokumenter eller rapporter, kan en Singleton-udskrivningstjeneste koordinere og administrere printjob, hvilket sikrer effektiv brug af udskrivningsressourcer.

8. Fordele ved Singleton Method Design Pattern:

  • Løser navnekollisioner: I scenarier, hvor et enkelt kontrolpunkt er nødvendigt for at undgå navngivningskonflikter eller kollisioner, sikrer Singleton-mønsteret, at der kun er én forekomst med et unikt navn.
  • Ivrig eller doven initialisering: Singleton-mønsteret understøtter både ivrig initialisering (oprettelse af forekomsten, når klassen er indlæst) og doven initialisering (oprettelse af forekomsten, når den først anmodes), hvilket giver fleksibilitet baseret på brugssagen.
  • Trådsikkerhed: Korrekt implementerede Singleton-mønstre kan give trådsikkerhed, hvilket sikrer, at instansen oprettes atomisk, og at flere tråde ikke utilsigtet skaber duplikerede instanser.
  • Reduceret hukommelsesfodaftryk: I applikationer, hvor ressourceforbrug er kritisk, kan Singleton-mønsteret bidrage til et reduceret hukommelsesfodaftryk ved at sikre, at der kun er én forekomst af klassen.

9. Ulemper ved Singleton Design Pattern

  • Test vanskeligheder: Fordi Singletons introducerer global tilstand, kan enhedstest blive udfordrende. At teste én komponent isoleret kan være mere kompliceret, hvis den er afhængig af en Singleton, da Singletonens tilstand kan påvirke resultatet af tests.
  • Samtidige problemer: I et multi-threaded miljø kan der være problemer relateret til oprettelse og initialisering af Singleton-instansen. Hvis flere tråde forsøger at skabe Singleton samtidigt, kan det resultere i løbsforhold.
  • Begrænset udvidelsesmuligheder: Singleton-mønsteret kan gøre koden mindre udvidelsesbar. Hvis du senere beslutter dig for, at du har brug for flere forekomster af klassen eller ønsker at ændre instansieringslogikken, kan det kræve betydelig refaktorering.
  • Global afhængighed: Singleton-mønsteret skaber en global afhængighed, hvilket gør det sværere at erstatte Singleton med en alternativ implementering eller at bruge afhængighedsinjektion til at levere instanser.
  • Svært at underklassificere: At underklassificere en Singleton kan være udfordrende. Fordi konstruktøren typisk er privat, kræver udvidelse af en Singleton yderligere pleje og følger muligvis ikke standard arvemønstre.
  • Livscyklusstyring: Singleton-mønsteret håndterer muligvis ikke scenarier, hvor instansen eksplicit skal destrueres eller nulstilles. Håndtering af Singletons livscyklus kan blive en bekymring.
  • Misbrug af globalt adgangspunkt: Selvom et globalt adgangspunkt er en fordel, kan det også misbruges. Udviklere kan blive fristet til at bruge Singleton til alt, hvilket fører til et overforbrug af den globale tilstand og et mindre modulært design.

10. Konklusion

Det er vigtigt for nogle klasser at have præcis én instans. Selvom der kan være mange printere i et system, bør der kun være én printerspooler. Der bør kun være ét filsystem og én vindueshåndtering. Et digitalt filter vil have en A/D-konverter. Et regnskabssystem vil blive dedikeret til at betjene én virksomhed. Hvordan sikrer vi, at en klasse kun har én instans, og at instansen er let tilgængelig? En global variabel gør et objekt tilgængeligt, men det forhindrer dig ikke i at instansiere flere objekter.

En bedre løsning er at gøre klassen selv ansvarlig for at holde styr på dens eneste instans. Klassen kan sikre, at ingen anden instans kan oprettes (ved at opsnappe anmodninger om at oprette nye objekter), og den kan give en måde at få adgang til instansen. Dette er Singleton-mønsteret.