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.
Défi
FacileConstruisons 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 classeGameSettingsqui 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) etplayerName(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)
- Une instance statique finale privée qui contient l’unique objet
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
playerNamepar "Hero",difficultypar "Hard" etsoundEnabledpar false - Obtenez une autre référence aux paramètres et appelez-la
settings2 - Appelez
displaySettings()sursettings2pour prouver qu’elle reflète les modifications effectuées viasettings1 - Affichez si
settings1etsettings2sont identiques en utilisant :Same instance: [true/false]
- Obtenez l’instance des paramètres et appelez-la
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: trueEssayez 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]
}
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
1Fondamentaux de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs objetsLe mot-clé thisMéthodesVariables d’instanceBases des constructeursRécapitulatif - Calculatrice simple4Sécurité face aux valeurs nulles
Introduction à la sécurité face aux valeurs nullesNullable vs Non-NullableLes opérateurs ? et !Mot-clé Late et sécurité face aux valeurs nullesOpérateurs sensibles à nullSécurité face aux valeurs nulles dans les classesRécapitulatif – Système de profil utilisateur7Classes abstraites et interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémenter ou étendreInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et génériques
Vue d’ensemble des List, Set et MapCollections à typage sûrClasses génériquesMéthodes génériquesContraintes génériquesIterable et IteratorRécapitulatif – stockage générique2Constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs redirigésRécapitulatif - Constructeur de formes5Encapsulation
Membres publics vs privésLa convention du préfixe _Confidentialité au niveau de la bibliothèqueApprofondissement des getters et settersMasquage de l’informationRécapitulatif - Fiches des étudiants8Mixins
Introduction aux MixinsCréer des MixinsUtiliser plusieurs MixinsMot-clé on dans les MixinsMixin ou héritageMixin ou interfaceRécapitulatif - Système animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode et ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy3Propriétés des classes
Membres d’instance et statiquesChamps Final et ConstVariables différéesMéthodes et champs statiquesAccesseurs et mutateursRécapitulatif - Gestionnaire de compte bancaire6Héritage
Héritage de baseLe mot-clé superRedéfinition de méthodeL’annotation @overrideLe mot-clé de classe finalConstructeurs et héritageRécapitulatif – Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification des types à l’exécutionLes opérateurs is et asMot-clé covariantRécapitulatif - Processeur de paiements12POO asynchrone
Futures et async/awaitNotions de base des StreamsContrôleurs de StreamsConstructeurs asynchronesAsynchrone dans les méthodes de classeRécapitulatif - récupérateur de données15Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron DépôtEntraînez-vous par vous-même : Compilateur Dart en ligne