Menu
Coddy logo textTech

Patron Singleton

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy. Leçon 90 sur 110.

Le pattern Singleton garantit qu'une classe n'a qu'une seule instance dans toute votre application et fournit un point d'accès global à celle-ci. C'est utile lorsqu'un seul objet est nécessaire pour coordonner les actions à travers le système - comme un gestionnaire de configuration, une connexion à une base de données ou un service de journalisation.

Dans Dart, vous pouvez implémenter un Singleton à l’aide d’un constructeur factory combiné à une instance statique privée :

class AppConfig {
  static final AppConfig _instance = AppConfig._internal();
  
  String appName = 'MyApp';
  String version = '1.0.0';
  
  // Constructeur nommé privé
  AppConfig._internal();
  
  // Le constructeur factory retourne la même instance
  factory AppConfig() {
    return _instance;
  }
}

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

Le constructeur privé _internal() empêche l'instanciation externe. Le champ statique _instance contient l'instance unique, créée une seule fois lors du chargement de la classe. Chaque appel à AppConfig() retourne cette même instance, de sorte que les modifications effectuées via une référence sont visibles partout.

Utilisez les Singletons avec parcimonie - ils introduisent un état global, ce qui peut rendre les tests plus difficiles. Ils sont mieux adaptés aux ressources véritablement partagées qui nécessitent un état cohérent dans toute votre application.

challenge icon

Défi

Facile

Construisons un gestionnaire des paramètres du jeu à l’aide du modèle Singleton ! Vous allez créer un système qui garantit qu’une seule instance des paramètres du jeu existe dans toute l’application, afin que toutes les parties de votre jeu partagent la même configuration.

Vous organiserez votre code dans deux fichiers :

  • game_settings.dart : créez une classe GameSettings qui implémente le modèle Singleton. Votre gestionnaire de paramètres doit comporter :
    • Une instance statique finale privée qui contient l’unique objet GameSettings
    • Un constructeur nommé privé pour empêcher l’instanciation externe
    • Un constructeur factory qui renvoie toujours la même instance
    • Trois champs de paramètres : difficulty (String, valeur par défaut : "Normal"), soundEnabled (bool, valeur par défaut : true) et playerName (String, valeur par défaut : "Player1")
    • Une méthode displaySettings() qui affiche les paramètres actuels dans ce format : Settings: [playerName] | Difficulty: [difficulty] | Sound: [on/off] (affichez "on" si soundEnabled vaut true, et "off" si sa valeur est false)
  • main.dart : importez vos paramètres de jeu et démontrez que le Singleton fonctionne correctement :
    • Obtenez l’instance des paramètres et appelez-la settings1
    • Appelez displaySettings() pour afficher les valeurs par défaut
    • Modifiez les paramètres : remplacez playerName par "Hero", difficulty par "Hard" et soundEnabled par false
    • Obtenez une autre référence aux paramètres et appelez-la settings2
    • Appelez displaySettings() sur settings2 pour prouver qu’elle reflète les modifications effectuées via settings1
    • Affichez si settings1 et settings2 sont identiques en utilisant : Same instance: [true/false]

Cela démontre l’avantage fondamental des Singletons : les modifications effectuées n’importe où dans votre application sont immédiatement visibles partout ailleurs, car il n’existe qu’une seule instance !

Résultat attendu :

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

Essayez vous-même

import 'game_settings.dart';

void main() {
  // TODO: Récupérer l'instance de settings et l'appeler settings1
  
  // TODO: Appeler displaySettings() pour afficher les valeurs par défaut
  
  // TODO: Modifier les paramètres :
  // - Changer playerName en "Hero"
  // - Changer difficulty en "Hard"
  // - Changer soundEnabled en false
  
  // TODO: Récupérer une autre référence à settings et l'appeler settings2
  
  // TODO: Appeler displaySettings() sur settings2 pour prouver qu'il reflète les changements
  
  // TODO: Afficher si settings1 et settings2 sont identiques
  // Format : Same instance: [true/false]
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Dart en ligne