Menu
Coddy logo textTech

Singleton-Muster

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 90 von 110.

Das Singleton-Muster stellt sicher, dass eine Klasse während der gesamten Anwendung nur eine einzige Instanz hat, und bietet einen globalen Zugriffspunkt darauf. Dies ist nützlich, wenn genau ein Objekt benötigt wird, um Aktionen im gesamten System zu koordinieren – wie ein Konfigurationsmanager, eine Datenbankverbindung oder ein Protokollierungsdienst.

In Dart kannst du ein Singleton mithilfe eines Factory-Konstruktors in Kombination mit einer privaten statischen Instanz implementieren:

class AppConfig {
  static final AppConfig _instance = AppConfig._internal();
  
  String appName = 'MyApp';
  String version = '1.0.0';
  
  // Privater benannter Konstruktor
  AppConfig._internal();
  
  // Factory-Konstruktor gibt dieselbe Instanz zurück
  factory AppConfig() {
    return _instance;
  }
}

void main() {
  var config1 = AppConfig();
  var config2 = AppConfig();
  
  config1.appName = 'UpdatedApp';
  
  print(config2.appName);  // UpdatedApp
  print(identical(config1, config2));  // true
}

Der private Konstruktor _internal() verhindert die Instanziierung von außen. Das statische Feld _instance enthält die einzige Instanz, die einmalig geladen wird, wenn die Klasse geladen wird. Jeder Aufruf von AppConfig() gibt dieselbe Instanz zurück, sodass Änderungen, die über eine Referenz vorgenommen werden, überall sichtbar sind.

Verwenden Sie Singletons sparsam – sie führen einen globalen Zustand ein, was das Testen erschweren kann. Sie eignen sich am besten für wirklich gemeinsam genutzte Ressourcen, die einen konsistenten Zustand über Ihre gesamte Anwendung hinweg erfordern.

challenge icon

Aufgabe

Einfach

Lass uns einen Spiel-Einstellungsmanager mithilfe des Singleton-Musters erstellen! Du erstellst ein System, das sicherstellt, dass während der gesamten Anwendung nur eine Instanz der Spieleinstellungen existiert, sodass alle Teile deines Spiels dieselbe Konfiguration verwenden.

Du organisierst deinen Code in zwei Dateien:

  • game_settings.dart: Erstelle eine GameSettings-Klasse, die das Singleton-Muster implementiert. Dein Einstellungsmanager sollte Folgendes enthalten:
    • Eine private statische finale Instanz, die das einzige GameSettings-Objekt enthält
    • Einen privaten benannten Konstruktor, um eine Instanziierung von außen zu verhindern
    • Einen Factory-Konstruktor, der immer dieselbe Instanz zurückgibt
    • Drei Einstellungsfelder: difficulty (String, Standardwert: "Normal"), soundEnabled (bool, Standardwert: true) und playerName (String, Standardwert: "Player1")
    • Eine Methode displaySettings(), die die aktuellen Einstellungen in diesem Format ausgibt: Settings: [playerName] | Difficulty: [difficulty] | Sound: [on/off] (gib "on" aus, wenn soundEnabled true ist, und "off", wenn es false ist)
  • main.dart: Importiere deine Spieleinstellungen und zeige, dass das Singleton korrekt funktioniert:
    • Rufe die Einstellungsinstanz ab und nenne sie settings1
    • Rufe displaySettings() auf, um die Standardwerte anzuzeigen
    • Ändere die Einstellungen: Setze playerName auf "Hero", difficulty auf "Hard" und soundEnabled auf false
    • Rufe eine weitere Referenz auf die Einstellungen ab und nenne sie settings2
    • Rufe displaySettings() für settings2 auf, um zu beweisen, dass die über settings1 vorgenommenen Änderungen widergespiegelt werden
    • Gib aus, ob settings1 und settings2 identisch sind, und verwende dafür: Same instance: [true/false]

Dies zeigt den Hauptvorteil von Singletons: Änderungen, die an beliebiger Stelle in deiner Anwendung vorgenommen werden, sind sofort überall sichtbar, weil es nur eine Instanz gibt!

Erwartete Ausgabe:

Settings: Player1 | Difficulty: Normal | Sound: on
Settings: Hero | Difficulty: Hard | Sound: off
Same instance: true

Probier es selbst

import 'game_settings.dart';

void main() {
  // TODO: Hol dir die settings-Instanz und nenne sie settings1
  
  // TODO: Rufe displaySettings() auf, um die Standardwerte anzuzeigen
  
  // TODO: Ändere die Einstellungen:
  // - Ändere playerName in "Hero"
  // - Ändere difficulty in "Hard"
  // - Ändere soundEnabled in false
  
  // TODO: Hol dir eine weitere Referenz auf settings und nenne sie settings2
  
  // TODO: Rufe displaySettings() für settings2 auf, um zu beweisen, dass es die Änderungen widerspiegelt
  
  // TODO: Gib aus, ob settings1 und settings2 identisch sind
  // Format: Same instance: [true/false]
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Dart-Compiler