Table des matières:

Comment faire le modèle de conception singleton en C++ : 9 étapes
Comment faire le modèle de conception singleton en C++ : 9 étapes

Vidéo: Comment faire le modèle de conception singleton en C++ : 9 étapes

Vidéo: Comment faire le modèle de conception singleton en C++ : 9 étapes
Vidéo: Рефакторинг: шаблон проектирования Singleton [Design Patterns] 2024, Novembre
Anonim
Comment faire le modèle de conception Singleton en C++
Comment faire le modèle de conception Singleton en C++

Introduction:

Le but de ce guide d'instructions est d'enseigner à l'utilisateur comment implémenter le modèle de conception singleton dans son programme C++. Ce faisant, cet ensemble d'instructions expliquera également au lecteur pourquoi les éléments d'un singleton sont tels qu'ils sont et comment le code est traité. Sachant cela, vous aidera à l'avenir à déboguer vos futurs singletons. Quel est le modèle de conception singleton? Le modèle de conception singleton est un modèle de conception dans lequel le codeur crée une classe qui ne peut être instanciée qu'une seule fois, les fonctions publiques des classes sont essentiellement accessibles n'importe où, à condition que vous ayez #inclus le fichier d'en-tête dans d'autres fichiers liés au projet.

Le modèle de conception singleton est un modèle de conception incontournable pour tout programmeur orienté objet, programmeur de logiciels et programmeur de jeux. Le modèle de conception singleton est également l'un des modèles de conception de codage les plus simples. L'apprendre peut vous aider à apprendre d'autres modèles de conception plus difficiles à l'avenir. Cela peut également vous aider à rationaliser le code de votre programme d'une manière que vous ne pensiez pas possible.

Alors que la difficulté du modèle de conception singleton est facile par rapport à d'autres modèles de conception, ce jeu d'instructions a une difficulté moyenne. Cela signifie que pour suivre ces instructions, nous vous recommandons de connaître les exigences syntaxiques de base et avancées du C++. Vous devez également connaître l'étiquette de codage C++ appropriée (c'est-à-dire garder les variables de classe privées, une classe par fichier d'en-tête, etc.). Vous devez également savoir comment libérer de la mémoire et comment fonctionnent les constructeurs et les destructeurs en C++.

Ce guide pédagogique prendra en moyenne environ 10 à 15 minutes.

Exigences matérielles:

-Un ordinateur (peut être PC ou Mac) capable d'exécuter Visual Studios (n'importe quelle version)

-Un programme simple, créé dans Visual Studios, avec lequel vous pouvez tester votre singleton

Remarque: le modèle de conception singleton peut être effectué sur n'importe quel autre IDE ou interface de codage prenant en charge C++, mais pour ce jeu d'instructions, nous utiliserons Visual Studios Enterprise Edition.

Étape 1: Créez votre classe, avec le fichier d'en-tête et le fichier CPP

Créez votre classe, avec le fichier d'en-tête et le fichier CPP
Créez votre classe, avec le fichier d'en-tête et le fichier CPP
Créez votre classe, avec le fichier d'en-tête et le fichier CPP
Créez votre classe, avec le fichier d'en-tête et le fichier CPP

Pour créer ces deux fichiers et la classe en même temps, ouvrez votre projet / programme dans Visual Studios, allez dans l'explorateur de solutions, faites un clic droit, et une boîte devrait apparaître près du curseur de votre souris, recherchez l'option "Ajouter", survolez dessus, et une autre case devrait apparaître à droite. Dans cette boîte, vous voulez trouver l'option "Nouvel élément..", cliquez dessus et une fenêtre, ressemblant à l'image de la photo 1.1 ci-dessous, devrait apparaître. Dans cette fenêtre, vous souhaitez sélectionner « Classe C++ », puis appuyez sur « Ajouter ». Cela ouvrira une autre fenêtre qui ressemble à l'image de la photo 1.2. Dans cette fenêtre, vous saisissez le nom de votre classe dans le champ "Nom de la classe" et Visual Studios nommera automatiquement le fichier réel après le nom de la classe. Pour les besoins de cette instruction, nous allons nommer notre classe "EngineDebugSingleton", mais il peut s'agir de n'importe quel nom à base de lettres. Vous pouvez maintenant appuyer sur « OK » et passer à l'étape 2.

Remarque: L'explorateur de solutions et l'endroit où les fichiers sont conservés sur votre ordinateur sont séparés. Déplacer ou créer quoi que ce soit dans l'explorateur de solutions ne déplacera ni n'organisera les fichiers dans l'explorateur de fichiers de votre système d'exploitation. Un moyen sûr d'organiser vos fichiers du côté de l'explorateur de fichiers serait de supprimer, mais pas de supprimer les fichiers spécifiques de l'explorateur de solutions, de déplacer les mêmes fichiers dans l'explorateur de fichiers à l'emplacement souhaité, puis de revenir à l'explorateur de solutions, faites un clic droit, recherchez l'option « Ajouter », puis recherchez « Élément existant » et recherchez les fichiers que vous avez déplacés. Assurez-vous de déplacer à la fois l'en-tête et le fichier cpp.

Étape 2: définissez le constructeur sur Privé

Définir le constructeur sur Privé
Définir le constructeur sur Privé

Avec votre fichier CPP et votre fichier d'en-tête nouvellement créés, s'il ne s'est pas ouvert automatiquement lorsque vous l'avez créé, accédez à l'explorateur de solutions et cliquez sur et ouvrez le "EngineDebugSingleton.h". Vous serez alors accueilli avec un "EngineDebugSingleton()", le constructeur par défaut de la classe et "~EngineDebugSingleton()" le destructeur de classe. Pour cette étape, nous voudrons définir le constructeur sur le privé, cela signifie que cette fonction n'est disponible que pour la classe et rien d'autre. Avec cela, vous ne pourrez pas créer de variable ou allouer la classe à la mémoire en dehors de la classe, uniquement dans le fichier d'en-tête des classes et les autres fonctions des classes. Avoir le constructeur privé est la clé du modèle de conception et du fonctionnement des singletons. Nous découvrirons dans les prochaines étapes comment un singleton est instancié et accessible.

La classe devrait maintenant ressembler à ceci après avoir déplacé le constructeur en privé (Regardez la photo associée)

Étape 3: définissez le destructeur sur Privé

Définir le destructeur sur Privé
Définir le destructeur sur Privé

Comme nous l'avons fait avec le constructeur dans

étape 2, pour cette étape, nous allons maintenant définir le destructeur sur private. Comme avec le constructeur, rien, à l'exception de la classe elle-même, ne pourra supprimer les variables de la classe de la mémoire.

La classe devrait maintenant ressembler à ceci après avoir terminé cette étape. (Voir photo associée)

Étape 4: Création d'une variable de pointeur statique dans le singleton

Création d'une variable de pointeur statique dans le singleton
Création d'une variable de pointeur statique dans le singleton

Dans cette étape, nous allons créer un

variable pointeur statique de type « EngineDebugSingleton* ». Ce sera la variable qui sera utilisée pour allouer notre singleton à la mémoire et pointera vers elle pendant tout le temps que notre singleton est alloué à la mémoire.

Voici à quoi devrait ressembler notre fichier d'en-tête après avoir créé cette variable

Étape 5: Création d'une fonction d'instance

Création d'une fonction d'instance
Création d'une fonction d'instance

Nous voulons maintenant créer une instance

fonction. La fonction devra être une fonction statique et voudra retourner une référence à notre classe ("EngineDebugSingleton&"). Nous avons appelé notre fonction Instance(). Dans la fonction elle-même, nous voudrons d'abord tester si ptrInstance == nullptr (peut être raccourci en !ptrInstance), si c'est nullptr, cela signifie que le singleton n'a pas été alloué et dans le cadre de l'instruction if, nous allons voulez allouer en faisant ptrInstance = new EngineDebugSingleton(). C'est là que vous allouez réellement le singleton à la mémoire. Après avoir quitté la portée de l'instruction if, nous retournerons ensuite vers quoi ptrInstance pointe, ce qui est indiqué par la syntaxe « *ptrInstance ». Nous utiliserons beaucoup cette fonction lors de la création de nos fonctions publiques statiques, nous pouvons donc vérifier si le singleton a été créé et alloué à la mémoire. En substance, cette fonction fait en sorte que vous ne puissiez avoir qu'une seule allocation de la classe et pas plus.

Voici à quoi devrait ressembler notre classe maintenant après avoir créé la fonction Instance(). Comme vous pouvez le voir, tout ce que nous avons fait est resté dans la section privée de la classe, cela va changer un peu dans les prochaines étapes.

Étape 6: Création de fonctions publiques statiques

Création de fonctions publiques statiques
Création de fonctions publiques statiques
Création de fonctions publiques statiques
Création de fonctions publiques statiques
Création de fonctions publiques statiques
Création de fonctions publiques statiques

Après avoir créé la fonction à partir de

étape 5, vous pouvez commencer à créer des fonctions publiques statiques. Chaque fonction publique doit avoir une fonction privée pour l'accompagner, le nom de cette fonction ne peut pas être le même. Pourquoi rendre la fonction statique ? Nous rendons les fonctions publiques statiques afin qu'elles soient accessibles sans objet réel. Donc, au lieu de faire quelque chose comme "EngineDebugSingleObj->SomeFunction()", nous faisons "EngineDebugSingleton:: Some Function()". Cela permet d'accéder à un singleton pratiquement n'importe où dans le code, à condition que vous ayez #inclus le fichier d'en-tête dans le fichier de projet spécifique avec lequel vous travaillez. Avec cela, vous pouvez également créer le singleton via l'une de ses fonctions publiques.

Pour nos besoins dans cette étape, nous avons créé deux fonctions void statiques publiques, « add() » et « subtract() ». Dans la section privée, nous avons deux autres fonctions, "PrivAdd()" et "PrivSubtract()". Nous avons également ajouté une variable int appelée "NumberOfThings". La définition de ces fonctions ira dans le fichier CPP de nos classes. Pour que la fonction entre facilement dans le fichier CPP, vous mettez en surbrillance, avec votre curseur, la fonction, qui devrait avoir une ligne verte en dessous, et appuyez sur « ALT gauche + ENTER », cela vous donnera la possibilité de créer la définition dans le fichier RPC associé aux classes. Voir la photo 6.1 pour voir à quoi devrait ressembler le fichier d'en-tête et après avoir créé toutes les définitions de fonction, votre CPP devrait ressembler à la photo 6.2, sauf que vos définitions de fonction n'auront aucun code.

Vous voudrez maintenant ajouter le même code que dans la photo 6.2 dans vos définitions de fonction. Comme indiqué précédemment, nos fonctions publiques utiliseront la fonction Instance(), qui renverra vers quoi ptrInstance pointe. Cela nous permet d'accéder aux fonctions privées de notre classe. Avec n'importe quelle fonction publique de singleton, vous ne devriez appeler que cette fonction d'instance. La seule exception à cela est notre fonction Terminer.

Remarque: les fonctions publiques et privées exactes indiquées dans cette étape ne sont pas nécessaires, vous pouvez avoir différents noms de fonction et opérations dans la fonction privée, mais pour tout type de fonction publique, vous devriez avoir une fonction privée pour l'accompagner et la fonction publique doit toujours utiliser, dans notre cas, la fonction Instance().

Étape 7: Création de la fonction de terminaison

Création de la fonction de terminaison
Création de la fonction de terminaison
Création de la fonction de terminaison
Création de la fonction de terminaison

Puisque nous ne pouvons désallouer notre singleton qu'à partir de la mémoire dans notre classe, nous devons créer une fonction publique statique. Cette fonction appellera delete sur ptrInstance, qui appelle le destructeur de classe, puis nous voudrons remettre ptrInstance à nullptr afin qu'il puisse être à nouveau alloué si votre programme ne se termine pas. Vous voudrez également mettre fin à vos singletons pour nettoyer toute mémoire allouée que vous avez allouée dans les variables privées de tout singleton.

Étape 8: définir PtrInstance sur Nullptr

Définition de PtrInstance sur Nullptr
Définition de PtrInstance sur Nullptr

Pour terminer votre singleton, vous souhaitez vous diriger vers le fichier EngineDebugSingleton. CPP et en haut du fichier CPP, dans notre exemple, tapez « EngineDebugSingleton * EngineDebugSingleton::ptrInstance = nullptr ».

Faire cela définira initialement ptrInstance sur nullptr, donc lorsque vous passerez par la fonction d'instance pour la première fois, notre classe sera autorisée à être allouée à la mémoire. Sans cela, vous obtiendrez probablement une erreur car vous essaierez d'accéder à une mémoire qui n'a rien qui lui soit allouée.

Étape 9: Test et conclusion

Test et conclusion
Test et conclusion

Nous allons maintenant vouloir tester notre singleton pour nous assurer qu'il fonctionne, cela impliquera que nous appelions les fonctions publiques comme décrit à l'étape 6 et nous vous recommandons de configurer des points d'arrêt pour parcourir votre code et voir que le singleton fonctionne comme ça devrait être. Notre point de départ sera dans le main.cpp de notre projet et notre main.cpp ressemble maintenant à l'image ci-dessous.

Toutes nos félicitations! Vous venez de terminer votre première implémentation du modèle de conception Singleton. Avec ce modèle de conception, vous pouvez désormais rationaliser votre code de différentes manières. Par exemple, vous pouvez désormais créer des systèmes de gestion qui fonctionnent tout au long de l'exécution de votre programme, auxquels vous pouvez accéder via des fonctions statiques partout où vous avez inclus la classe.

Votre fichier d'en-tête final devrait ressembler à la photo 7.1. Le fichier CPP associé à votre singleton doit ressembler à la photo 6.2 avec l'ajout, en haut du fichier, du code indiqué à l'étape 8. Cette instruction vous a fourni une structure simple du modèle de conception de singleton.

Conseils de dépannage:

Obtenir des erreurs liées à la mémoire ?

Assurez-vous de vous référer aux étapes 7 et 8 pour vous assurer que vous définissez ptrInstance sur nullptr.

Une boucle infinie se produit ?

Assurez-vous que pour les fonctions publiques, dans leurs définitions, vous appelez la fonction privée, pas la même fonction publique.

Objets alloués au sein du singleton provoquant des fuites de mémoire ?

Assurez-vous d'appeler la fonction de terminaison de votre singleton lorsque cela est approprié dans votre code de programme, et dans le destructeur de votre singleton, assurez-vous de désallouer tous les objets qui ont été alloués à la mémoire dans le cadre du code du singleton.