Menu
Coddy logo textTech

Wzorzec Singleton

Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 90 z 110.

Wzorzec Singleton gwarantuje, że klasa ma tylko jedną instancję w całej aplikacji, i zapewnia globalny punkt dostępu do niej. Jest to przydatne, gdy do koordynowania działań w całym systemie potrzebny jest dokładnie jeden obiekt — na przykład menedżer konfiguracji, połączenie z bazą danych lub usługa logowania.

W Dart możesz zaimplementować wzorzec Singleton za pomocą konstruktora factory połączonego z prywatną instancją statyczną:

class AppConfig {
  static final AppConfig _instance = AppConfig._internal();
  
  String appName = 'MyApp';
  String version = '1.0.0';
  
  // Prywatny konstruktor nazwany
  AppConfig._internal();
  
  // Konstruktor fabryczny zwraca tę samą instancję
  factory AppConfig() {
    return _instance;
  }
}

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

Prywatny konstruktor _internal() uniemożliwia tworzenie instancji z zewnątrz. Pole statyczne _instance przechowuje jedyną instancję, utworzoną raz podczas ładowania klasy. Każde wywołanie AppConfig() zwraca tę samą instancję, więc zmiany wprowadzone za pomocą jednego odwołania są widoczne wszędzie.

Używaj wzorców Singleton oszczędnie — wprowadzają stan globalny, co może utrudnić testowanie. Najlepiej sprawdzają się w przypadku zasobów współdzielonych, które muszą zachowywać spójny stan w całej aplikacji.

challenge icon

Wyzwanie

Łatwy

Stwórzmy menedżera ustawień gry, używając wzorca Singleton! Utworzysz system, który zapewnia, że w całej aplikacji istnieje tylko jedna instancja ustawień gry, dzięki czemu wszystkie części gry korzystają z tej samej konfiguracji.

Podzielisz kod na dwa pliki:

  • game_settings.dart: Utwórz klasę GameSettings, która implementuje wzorzec Singleton. Menedżer ustawień powinien mieć:
    • Prywatną statyczną instancję final, która przechowuje jedyny obiekt GameSettings
    • Prywatny konstruktor nazwany, który zapobiega tworzeniu instancji z zewnątrz
    • Konstruktor fabryczny, który zawsze zwraca tę samą instancję
    • Trzy pola ustawień: difficulty (String, wartość domyślna: "Normal"), soundEnabled (bool, wartość domyślna: true) i playerName (String, wartość domyślna: "Player1")
    • Metodę displaySettings(), która wyświetla bieżące ustawienia w tym formacie: Settings: [playerName] | Difficulty: [difficulty] | Sound: [on/off] (wyświetl "on", jeśli soundEnabled ma wartość true, a "off", jeśli ma wartość false)
  • main.dart: Zaimportuj ustawienia gry i pokaż, że Singleton działa poprawnie:
    • Pobierz instancję ustawień i nazwij ją settings1
    • Wywołaj displaySettings(), aby wyświetlić wartości domyślne
    • Zmień ustawienia: ustaw playerName na "Hero", difficulty na "Hard", a soundEnabled na false
    • Pobierz kolejne odwołanie do ustawień i nazwij je settings2
    • Wywołaj displaySettings() dla settings2, aby potwierdzić, że odzwierciedla zmiany wprowadzone za pomocą settings1
    • Wyświetl informację, czy settings1 i settings2 są identyczne, używając formatu: Same instance: [true/false]

To pokazuje główną zaletę wzorca Singleton — zmiany wprowadzone w dowolnym miejscu aplikacji są natychmiast widoczne wszędzie indziej, ponieważ istnieje tylko jedna instancja!

Oczekiwany wynik:

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

Spróbuj swoich sił

import 'game_settings.dart';

void main() {
  // TODO: Pobierz instancję ustawień i nazwij ją settings1
  
  // TODO: Wywołaj displaySettings(), aby wyświetlić wartości domyślne
  
  // TODO: Zmodyfikuj ustawienia:
  // - Zmień playerName na "Hero"
  // - Zmień difficulty na "Hard"
  // - Zmień soundEnabled na false
  
  // TODO: Pobierz kolejne odwołanie do ustawień i nazwij je settings2
  
  // TODO: Wywołaj displaySettings() na settings2, aby pokazać, że odzwierciedla zmiany
  
  // TODO: Wyświetl, czy settings1 i settings2 są identyczne
  // Format: Same instance: [true/false]
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Dart online