Singleton-Muster
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 65 von 87.
Das Singleton Pattern ist ein erzeugendes Entwurfsmuster, das sicherstellt, dass eine Klasse während der gesamten Anwendung nur eine Instanz hat, und gleichzeitig einen globalen Zugriffspunkt auf diese Instanz bereitstellt. Dies ist nützlich für Ressourcen, die gemeinsam genutzt werden sollten, wie etwa Konfigurationsmanager, Verbindungspools oder Protokollierungsdienste.
Das Muster funktioniert, indem der Konstruktor privat gemacht wird, wodurch eine direkte Instanziierung verhindert wird. Stattdessen steuert eine statische Methode den Zugriff auf die einzige Instanz:
public class DatabaseConnection {
private static DatabaseConnection instance;
// Privater Konstruktor verhindert direkte Instanziierung
private DatabaseConnection() {
System.out.println("Connection created");
}
// Globaler Zugriffspunkt
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
public void query(String sql) {
System.out.println("Executing: " + sql);
}
}Jeder Aufruf von getInstance() gibt dasselbe Objekt zurück. Die Instanz wird erst erstellt, wenn sie erstmals angefordert wird. Dies wird als verzögerte Initialisierung bezeichnet:
DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();
System.out.println(db1 == db2); // true - same instanceDie wichtigsten Bestandteile eines Singleton sind: ein private static-Feld, das die Instanz enthält, ein private-Konstruktor und eine public static-Methode, die die Instanz zurückgibt. Diese Kombination garantiert, dass du unabhängig davon, wie oft du das Objekt anforderst, immer dasselbe erhältst.
Aufgabe
EinfachErstellen wir einen Konfigurationsmanager für eine Anwendung mithilfe des Singleton-Musters! Dein Konfigurationsmanager stellt sicher, dass alle Teile deiner Anwendung dieselben Einstellungen verwenden, unabhängig davon, wie oft sie darauf zugreifen.
Du wirst deinen Code auf zwei Dateien verteilen:
AppConfig.java: Erstelle eine Singleton-Klasse, die die Konfigurationseinstellungen der Anwendung verwaltet. DeineAppConfigsollte Folgendes enthalten:Ein privates statisches Feld, das die einzige Instanz speichert.
Ein privates String-Feld namens
appNameund ein privates int-Feld namensmaxUsers.Einen privaten Konstruktor, der
appNameauf"MyApplication"undmaxUsersauf100setzt und anschließendAppConfig initializedausgibt.Eine öffentliche statische Methode
getInstance(), die die Instanz nur erstellt, wenn sie noch nicht existiert (verzögerte Initialisierung), und sie anschließend zurückgibt.Eine Methode
setAppName(String name), die den Namen der Anwendung aktualisiert.Eine Methode
setMaxUsers(int max), die die maximale Benutzeranzahl aktualisiert.Eine Methode
displaySettings(), dieApp: [appName], Max Users: [maxUsers]ausgibt.Main.java: Zeige, dass dein Singleton korrekt funktioniert! Du erhältst zwei Eingaben: einen neuen Anwendungsnamen (String) und einen neuen Wert für die maximale Benutzeranzahl (Ganzzahl).Rufe zuerst eine Instanz von
AppConfigab und speichere sie in einer Variable namensconfig1. RufedisplaySettings()auf, um die Standardwerte anzuzeigen.Aktualisiere dann die Einstellungen mithilfe deiner Eingabewerte, indem du
setAppNameundsetMaxUsersfürconfig1aufrufst.Rufe eine weitere Instanz ab und speichere sie in
config2. RufedisplaySettings()fürconfig2auf, um zu beweisen, dass sie die überconfig1vorgenommenen Änderungen widerspiegelt.Gib schließlich aus, ob beide Referenzen auf dasselbe Objekt zeigen:
Same instance: [true/false], indem duconfig1 == config2vergleichst.
Du erhältst zwei Eingaben in dieser Reihenfolge: den neuen Anwendungsnamen (String) und den neuen Wert für die maximale Benutzeranzahl (Ganzzahl).
Diese Aufgabe veranschaulicht den zentralen Vorteil des Singleton-Musters: Unabhängig davon, wie oft du die Konfiguration anforderst, erhältst du immer dieselbe Instanz mit demselben gemeinsamen Zustand!
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String newAppName = scanner.nextLine();
int newMaxUsers = scanner.nextInt();
// TODO: Erste Instanz von AppConfig holen und in config1 speichern
// TODO: displaySettings() auf config1 aufrufen, um Standardwerte anzuzeigen
// TODO: Einstellungen mit setAppName und setMaxUsers auf config1 aktualisieren
// TODO: Eine weitere Instanz holen und in config2 speichern
// TODO: displaySettings() auf config2 aufrufen, um zu beweisen, dass Änderungen geteilt werden
// TODO: Ausgeben, ob beide Referenzen auf dasselbe Objekt zeigen:
// "Same instance: [true/false]" using config1 == config2
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenFelder (Attribute)KonstruktormethodeÜberladen von KonstruktorenRückblick – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbung (extends)Das Schlüsselwort superÜberschreiben von Methoden (@Override)KonstruktorverkettungDie Object-KlasseEinfach- und mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenRückblick – Mitarbeiterhierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-SchnittstelleRückblick – Benutzerdefinierte Sortierung2Zugriffsmodifikatoren & Kapselung
Übersicht der ZugriffsebenenGetter- und Setter-MethodenInformationsverbergungDas Schlüsselwort finalRückblick – Bankkontoverwaltung5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenRückblick – Formrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, verschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Versiegelte Klassen (Java 17+)11Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBuilder-MusterObserver-MusterStrategie-Muster14Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungsdienst3Klassen-Props & statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Wiederholung – Counter & Utility6Schnittstellen & abstrakte Klassen
Einführung in InterfacesInterfaces implementierenMehrere Interfaces implementierenDefault & Static in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesRückblick – ZahlungssystemÜbe selbstständig: Online-Java-Compiler