logo

Entwurfsmuster der Singleton-Methode

Das Singleton-Muster ist wahrscheinlich das am weitesten verbreitete Designmuster. Es ist ein einfaches Muster, leicht zu verstehen und zu verwenden. Manchmal wird es im Übermaß und in Situationen verwendet, in denen es nicht erforderlich ist. In solchen Fällen überwiegen die Nachteile der Nutzung die Vorteile, die sie mit sich bringt. Aus diesem Grund wird das Singleton-Muster manchmal als ein Muster betrachtet Antimuster oder Muster-Singleton .

Singleton-Methode-Design-Pattern



Wichtige Themen für das Entwurfsmuster der Singleton-Methode

Java-Arraylist-Sortierung

1. Was ist das Designmuster der Singleton-Methode?

Die Singleton-Methode oder das Singleton-Entwurfsmuster ist eines der einfachsten Entwurfsmuster. Es stellt sicher, dass eine Klasse nur eine Instanz hat und bietet einen globalen Zugriffspunkt darauf.

2. Wann sollte das Designmuster der Singleton-Methode verwendet werden?

Verwenden Sie die Singleton-Methode Design Pattern, wenn:



  • Es muss genau eine Instanz einer Klasse geben und diese muss für Clients von einem bekannten Zugangspunkt aus zugänglich sein.
  • Wenn die einzige Instanz durch Unterklassen erweiterbar sein sollte und Clients in der Lage sein sollten, eine erweiterte Instanz ohne Änderungen zu verwenden
  • Singleton-Klassen werden für Protokollierung, Treiberobjekte, Caching und Thread-Pool-Datenbankverbindungen verwendet.

3. Initialisierungstypen von Singleton

Die Singleton-Klasse kann mit zwei Methoden instanziiert werden:

  • Frühe Initialisierung: Bei dieser Methode wird die Klasse unabhängig davon initialisiert, ob sie verwendet werden soll oder nicht. Der Hauptvorteil dieser Methode ist ihre Einfachheit. Sie initiieren die Klasse zum Zeitpunkt des Ladens der Klasse. Der Nachteil besteht darin, dass die Klasse immer initialisiert wird, unabhängig davon, ob sie verwendet wird oder nicht.
  • Verzögerte Initialisierung: Bei dieser Methode wird die Klasse nur dann initialisiert, wenn sie erforderlich ist. Dies erspart Ihnen die Instanziierung der Klasse, wenn Sie sie nicht benötigen. Im Allgemeinen wird die verzögerte Initialisierung verwendet, wenn wir eine Singleton-Klasse erstellen.

4. Schlüsselkomponente des Entwurfsmusters der Singleton-Methode:

Schlüsselkomponente des Singleton-Methodenentwurfsmusters (1)

4.1. Statisches Mitglied:

Das Singleton-Muster oder Muster Singleton verwendet ein statisches Mitglied innerhalb der Klasse. Dieses statische Mitglied stellt sicher, dass Speicher nur einmal zugewiesen wird, wodurch die einzelne Instanz der Singleton-Klasse erhalten bleibt.



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

4.2. Privater Bauunternehmer:

Das Singleton-Muster oder Muster-Singleton enthält einen privaten Konstruktor, der als Barriere gegen externe Versuche dient, Instanzen der Singleton-Klasse zu erstellen. Dadurch wird sichergestellt, dass die Klasse die Kontrolle über ihren Instanziierungsprozess hat.

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

4.3. Statische Factory-Methode:

Ein entscheidender Aspekt des Singleton-Musters ist das Vorhandensein einer statischen Factory-Methode. Diese Methode fungiert als Gateway und bietet einen globalen Zugriffspunkt auf das Singleton-Objekt. Wenn jemand eine Instanz anfordert, erstellt diese Methode entweder eine neue Instanz (falls keine vorhanden ist) oder gibt die vorhandene Instanz an den Aufrufer zurück.

for-Schleife im Shell-Skript
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. Implementierung des Singleton-Methodenentwurfsmusters

Die Implementierung eines Singleton Design Pattern bzw. Pattern Singleton wird im folgenden Klassendiagramm beschrieben:

Screenshot-2023-12-07-174635

Implementierung des Entwurfsmusters der Singleton-Methode

Die Implementierung des Singleton-Designmusters ist sehr einfach und besteht aus einer einzigen Klasse. Um sicherzustellen, dass die Singleton-Instanz eindeutig ist, sollten alle Singleton-Konstruktoren privat gemacht werden. Der globale Zugriff erfolgt über eine statische Methode, auf die global auf eine einzelne Instanz zugegriffen werden kann, wie im Code gezeigt.

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

Ausgabe
Singleton is Instantiated. Somethong is Done.>

Mit der getInstance-Methode prüfen wir, ob die Instanz null ist. Wenn die Instanz nicht null ist, bedeutet dies, dass das Objekt zuvor erstellt wurde; andernfalls erstellen wir es mit dem neuen Operator.

6. Verschiedene Möglichkeiten zur Implementierung des Entwurfsmusters für Singleton-Methoden

Manchmal benötigen wir nur eine Instanz unserer Klasse, beispielsweise eine einzelne DB-Verbindung, die von mehreren Objekten gemeinsam genutzt wird, da die Erstellung einer separaten DB-Verbindung für jedes Objekt kostspielig sein kann. Ebenso kann es in einer Anwendung einen einzelnen Konfigurationsmanager oder Fehlermanager geben, der alle Probleme behandelt, anstatt mehrere Manager zu erstellen.

Klassische Umsetzung

Sehen wir uns verschiedene Designoptionen für die Implementierung einer solchen Klasse an. Wenn Sie statische Klassenvariablen und Zugriffsmodifikatoren gut beherrschen, sollte dies keine schwierige Aufgabe sein.

Methode 1 – Klassische Implementierung || Machen Sie getInstance() für die Implementierung statisch Entwurfsmuster der Singleton-Methode

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

Hier haben wir erklärt bekomme Instanz() static, damit wir es aufrufen können, ohne die Klasse zu instanziieren. Das erste Mal bekomme Instanz() aufgerufen wird, erstellt es ein neues Singleton-Objekt und gibt danach einfach dasselbe Objekt zurück.

Notiz: Singleton obj wird erst erstellt, wenn wir es benötigen und aufrufen bekomme Instanz() Methode. Dies wird als verzögerte Instanziierung bezeichnet. Das Hauptproblem bei der oben genannten Methode besteht darin, dass sie nicht threadsicher ist. Betrachten Sie die folgende Ausführungssequenz.

Diese Ausführungssequenz erstellt zwei Objekte für den Singleton. Daher ist diese klassische Implementierung nicht threadsicher.

Methode 2 || Machen Sie getInstance() mit der Implementierung synchronisiert Entwurfsmuster der Singleton-Methode

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

Hier stellt die Verwendung von synchronisiert sicher, dass jeweils nur ein Thread ausgeführt werden kann bekomme Instanz() . Der Hauptnachteil dieser Methode besteht darin, dass die Verwendung von „synced every time“ beim Erstellen des Singleton-Objekts teuer ist und die Leistung Ihres Programms beeinträchtigen kann. Wenn jedoch die Leistung von bekomme Instanz() Ist für Ihre Anwendung nicht kritisch, bietet diese Methode eine saubere und einfache Lösung.

Methode 3 – Eagere Instanziierung || Statische Initialisierungsbasierte Implementierung des Singleton-Entwurfsmusters

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

Hier haben wir eine Instanz eines Singletons in einem statischen Initialisierer erstellt. JVM führt beim Laden der Klasse einen statischen Initialisierer aus und ist daher garantiert threadsicher. Verwenden Sie diese Methode nur, wenn Ihre Singleton-Klasse leicht ist und während der gesamten Ausführung Ihres Programms verwendet wird.

Methode 4 – Am effizientesten || Verwenden Sie Double Checked Locking, um ein Singleton-Entwurfsmuster zu implementieren

Wenn Sie sorgfältig darauf achten, ist die Synchronisierung nach der Erstellung eines Objekts nicht mehr sinnvoll, da obj jetzt nicht null ist und jede Abfolge von Vorgängen zu konsistenten Ergebnissen führt. Daher erhalten wir die Sperre für getInstance() nur einmal, wenn das Objekt null ist. Auf diese Weise synchronisieren wir nur den ersten Durchgang, genau das, was wir wollen.

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

Wir haben das Objekt deklariert flüchtig Dadurch wird sichergestellt, dass mehrere Threads die obj-Variable korrekt anbieten, wenn sie für die Singleton-Instanz initialisiert wird. Diese Methode reduziert den Aufwand für jedes Mal, wenn die synchronisierte Methode aufgerufen wird, drastisch.

Singleton-Designmuster Java

7. Anwendungsfall der Pattern-Singleton-Methode

  • Datenbankverbindungen: In Anwendungen, in denen das Erstellen und Verwalten von Datenbankverbindungen ein kostspieliger Vorgang ist, kann ein Singleton verwendet werden, um eine einzelne Datenbankverbindung in der gesamten Anwendung aufrechtzuerhalten.
  • Konfigurationsmanagement: Wenn Sie über globale Konfigurationseinstellungen verfügen, auf die verschiedene Komponenten der Anwendung zugreifen müssen, kann ein Singleton-Konfigurationsmanager einen zentralen Zugriffspunkt auf diese Einstellungen bereitstellen.
  • GUI-Komponenten: Für Komponenten oder Controller der grafischen Benutzeroberfläche (GUI) kann ein Singleton dabei helfen, den Status und die Aktionen der Benutzeroberfläche zu verwalten und einen zentralen Kontrollpunkt bereitzustellen.
  • Gerätemanager: In eingebetteten Systemen oder Anwendungen, die mit Hardwaregeräten interagieren, kann ein Singleton verwendet werden, um den Zugriff auf Hardwaregeräte zu verwalten und zu steuern, um Konflikte zu vermeiden.
  • Druckservice: In Systemen, die das Drucken von Dokumenten oder Berichten umfassen, kann ein Singleton-Druckdienst Druckaufträge koordinieren und verwalten und so eine effiziente Nutzung der Druckressourcen gewährleisten.

8. Vorteile des Singleton-Methodenentwurfsmusters:

  • Behebt Namenskollisionen: In Szenarien, in denen ein einziger Kontrollpunkt erforderlich ist, um Namenskonflikte oder Kollisionen zu vermeiden, stellt das Singleton-Muster sicher, dass es nur eine Instanz mit einem eindeutigen Namen gibt.
  • Eifrige oder faule Initialisierung: Das Singleton-Muster unterstützt sowohl die Eager-Initialisierung (Erstellen der Instanz, wenn die Klasse geladen wird) als auch die Lazy-Initialisierung (Erstellen der Instanz, wenn sie zum ersten Mal angefordert wird) und bietet so Flexibilität je nach Anwendungsfall.
  • Thread-Sicherheit: Richtig implementierte Singleton-Muster können Thread-Sicherheit bieten und sicherstellen, dass die Instanz atomar erstellt wird und dass mehrere Threads nicht versehentlich doppelte Instanzen erstellen.
  • Reduzierter Speicherbedarf: In Anwendungen, bei denen der Ressourcenverbrauch von entscheidender Bedeutung ist, kann das Singleton-Muster zu einem geringeren Speicherbedarf beitragen, indem sichergestellt wird, dass nur eine Instanz der Klasse vorhanden ist.

9. Nachteile des Singleton-Entwurfsmusters

  • Testschwierigkeiten: Da Singletons einen globalen Zustand einführen, können Unit-Tests zu einer Herausforderung werden. Das isolierte Testen einer Komponente kann komplizierter sein, wenn sie auf einem Singleton basiert, da der Status des Singletons das Testergebnis beeinflussen kann.
  • Probleme mit der Parallelität: In einer Multithread-Umgebung können Probleme im Zusammenhang mit der Erstellung und Initialisierung der Singleton-Instanz auftreten. Wenn mehrere Threads gleichzeitig versuchen, den Singleton zu erstellen, kann es zu Race Conditions kommen.
  • Begrenzte Erweiterbarkeit: Das Singleton-Muster kann dazu führen, dass Code weniger erweiterbar ist. Wenn Sie später entscheiden, dass Sie mehrere Instanzen der Klasse benötigen oder die Instanziierungslogik ändern möchten, ist möglicherweise eine umfassende Umgestaltung erforderlich.
  • Globale Abhängigkeit: Das Singleton-Muster erzeugt eine globale Abhängigkeit, was es schwieriger macht, den Singleton durch eine alternative Implementierung zu ersetzen oder die Abhängigkeitsinjektion zum Bereitstellen von Instanzen zu verwenden.
  • Schwer zu unterordnen: Die Unterklassifizierung eines Singleton kann eine Herausforderung sein. Da der Konstruktor normalerweise privat ist, erfordert die Erweiterung eines Singletons zusätzliche Sorgfalt und folgt möglicherweise nicht den Standardvererbungsmustern.
  • Lebenszyklusverwaltung: Das Singleton-Muster behandelt möglicherweise keine Szenarien, in denen die Instanz explizit zerstört oder zurückgesetzt werden muss. Die Verwaltung des Lebenszyklus des Singleton kann zu einem Problem werden.
  • Missbrauch globaler Zugangspunkte: Ein globaler Zugangspunkt ist zwar von Vorteil, kann aber auch missbraucht werden. Entwickler könnten versucht sein, den Singleton für alles zu verwenden, was zu einer übermäßigen Nutzung des globalen Status und einem weniger modularen Design führen würde.

10. Fazit

Für einige Klassen ist es wichtig, genau eine Instanz zu haben. Obwohl es in einem System viele Drucker geben kann, sollte es nur einen Druckerspooler geben. Es sollte nur ein Dateisystem und einen Fenstermanager geben. Ein digitaler Filter verfügt über einen A/D-Wandler. Ein Buchhaltungssystem wird für die Bedienung eines Unternehmens bestimmt. Wie stellen wir sicher, dass eine Klasse nur eine Instanz hat und dass die Instanz leicht zugänglich ist? Eine globale Variable macht ein Objekt zugänglich, hindert Sie jedoch nicht daran, mehrere Objekte zu instanziieren.

Eine bessere Lösung besteht darin, die Klasse selbst dafür verantwortlich zu machen, den Überblick über ihre einzige Instanz zu behalten. Die Klasse kann sicherstellen, dass keine andere Instanz erstellt werden kann (indem sie Anfragen zum Erstellen neuer Objekte abfängt), und sie kann eine Möglichkeit bieten, auf die Instanz zuzugreifen. Dies ist das Singleton-Muster.