Que recherchez-vous ?
Hero background image
Comment utiliser le modèle de la fabrique pour la création d'objets au moment de l'exécution ?

L'implémentation de modèles de programmation de jeux courants dans votre projet Unity peut vous aider à construire et à maintenir efficacement une base de code propre, organisée et lisible. Les modèles de conception réduisent le temps de remaniement et de test, accélérant les processus de développement et contribuant à une base solide pour développer votre jeu, votre équipe et votre entreprise.

Ne considérez pas les modèles de conception comme des solutions finies que vous pouvez copier et coller dans votre code, mais comme des outils supplémentaires qui peuvent vous aider à construire des applications plus vastes et évolutives.

Cette page explique le modèle de conception d'une usine.

Le contenu ici est basé sur le livre électronique gratuit, Améliorez votre code avec des modèles de programmation de jeux.

Consultez d'autres articles de la série sur les modèles de conception de la programmation des jeux Unity sur le hub des meilleures pratiques Unity ou via ces liens :

Schéma d'usine
UN MODÈLE DE CONCEPTION D'USINE FOURNIT UNE INTERFACE POUR LA CRÉATION D'OBJETS DANS UNE SUPERCLASSE, MAIS PERMET AUX SOUS-CLASSES DE MODIFIER LE TYPE D'OBJETS QUI SERONT CRÉÉS
Comprendre le modèle d'usine

Il est parfois utile d'avoir un objet spécial qui crée d'autres objets. De nombreux jeux génèrent une variété de choses au cours du jeu, et vous ne savez souvent pas ce dont vous avez besoin au moment de l'exécution jusqu'à ce que vous en ayez réellement besoin.

Le modèle de fabrique désigne un objet spécial appelé - vous l'avez deviné - une fabrique à cette fin. D'une part, il résume de nombreux détails liés à la création de ses "produits". L'avantage immédiat est de désencombrer votre code.

Toutefois, si chaque produit suit une interface ou une classe de base commune, vous pouvez aller plus loin et faire en sorte qu'il contienne une plus grande part de sa propre logique de construction, en la dissimulant à la fabrique elle-même. La création de nouveaux objets devient ainsi plus extensible.

Vous pouvez également sous-classer l'usine pour créer plusieurs usines dédiées à des produits spécifiques. Cela permet de générer des ennemis, des obstacles ou toute autre chose au moment de l'exécution.

Projet d'exemple d'usine
UN PRODUIT JOUE UN SON, TANDIS QU'UN AUTRE JOUE DES PARTICULES. LES DEUX UTILISENT LA MÊME INTERFACE.
Testez la configuration usine dans un exemple de projet

Un exemple de projet est disponible sur GitHub. Il présente différents modèles de programmation dans le contexte du développement d'un jeu, y compris le modèle d'usine.

L'exemple de modèle d'usine consiste en un code permettant à un joueur de se déplacer dans un labyrinthe. Dans le labyrinthe, vous pouvez faire apparaître deux GameObjects différents appelés produits en cliquant. Ils utilisent tous deux la même interface et partagent une forme similaire, mais l'un génère des particules et l'autre joue un son.

La scène du motif d'usine se trouve dans le dossier intitulé "6 Factory".

Création d'une usine simple

Imaginez que vous souhaitiez créer un modèle de fabrique pour instancier des éléments pour un niveau de jeu. Vous pouvez utiliser les Prefabs pour créer des GameObjects, mais vous pouvez aussi vouloir exécuter un comportement personnalisé lors de la création de chaque instance.

Plutôt que d'utiliser des instructions if ou un commutateur pour maintenir cette logique, créez une interface appelée IProduct et une classe abstraite appelée Factory, comme indiqué dans l'exemple de code.

Les produits doivent suivre un modèle spécifique pour leurs méthodes, mais ils ne partagent aucune autre fonctionnalité. Vous définissez donc l'interface IProduct.

Les usines peuvent avoir besoin de fonctionnalités communes partagées, c'est pourquoi cet exemple utilise des classes abstraites. Il suffit de tenir compte de la substitution de Liskov des principes SOLID lors de l'utilisation des sous-classes. Il stipule que les objets d'une superclasse doivent pouvoir être remplacés par des objets d'une sous-classe sans affecter la correction du programme. En d'autres termes, tout programme qui utilise une référence à une superclasse doit pouvoir utiliser n'importe laquelle de ses sous-classes sans le savoir.

L'UTILISATION D'UNE INTERFACE POUR DÉFINIR LES PROPRIÉTÉS ET LA LOGIQUE PARTAGÉES ENTRE VOS PRODUITS
L'UTILISATION D'UNE INTERFACE POUR DÉFINIR LES PROPRIÉTÉS ET LA LOGIQUE PARTAGÉES ENTRE VOS PRODUITS
Organisation de la formation dans un exemple de projet

L'interface IProduct définit ce qui est commun entre vos produits. Dans ce cas, vous avez simplement une propriété ProductName et toute logique que le produit exécute sur Initialize.

Vous pouvez alors définir autant de produits que vous le souhaitez(ProduitA, ProduitB, etc.) à condition qu'ils respectent l'interface IProduct.

La classe de base, Factory, possède une méthode GetProduct qui renvoie un IProduct. Elle est abstraite, vous ne pouvez donc pas créer directement des instances de Factory. Vous dérivez deux sous-classes concrètes(ConcreteFactoryA et ConcreteFactoryB), qui obtiendront les différents produits.

Dans cet exemple, GetProduct prend une position Vector3 afin de faciliter l'instanciation d'un objet de jeu préfabriqué à un endroit précis. Un champ dans chaque usine de béton stocke également le modèle Prefab correspondant.

Le résultat est une structure qui ressemble à l'image ci-dessus.

Exemple de code

Dans l'extrait de code, vous pouvez voir un exemple de ProductA et de ConcreteFactoryA.

Ici, vous avez fait en sorte que les classes de produits MonoBehaviours qui implémentent IProduct tirent parti des Prefabs dans l'usine.

Notez que chaque produit peut avoir sa propre version de Initialize. L'exemple ProductA Prefab contient un ParticleSystem, qui joue lorsque la ConcreteFactoryA instancie une copie. La fabrique elle-même ne contient pas de logique spécifique pour déclencher les particules ; elle invoque uniquement la méthode Initialize, qui est commune à tous les produits.

Explorez l'exemple de projet pour voir comment le composant ClickToCreate passe d'une usine à l'autre pour créer ProductA et ProductB, qui ont des comportements différents. Le produit B émet un son lorsqu'il apparaît, tandis que le produit A déclenche un effet de particule pour illustrer le concept de base des variations de produit.

Avantages et inconvénients

Vous tirerez le meilleur parti du modèle d'usine lorsque vous configurerez de nombreux produits. La définition de nouveaux types de produits dans votre application ne modifie pas les types de produits existants et ne nécessite pas de modifier le code précédent.

En séparant la logique interne de chaque produit dans sa propre classe, le code de l'usine reste relativement court. Chaque usine sait seulement qu'elle doit invoquer Initialize pour chaque produit, sans avoir connaissance des détails sous-jacents.

L'inconvénient est que vous devez créer un certain nombre de classes et de sous-classes pour mettre en œuvre le modèle. Comme les autres modèles, il introduit un peu de frais généraux, qui peuvent être inutiles si vous n'avez pas une grande variété de produits. D'un autre côté, le temps initial consacré à la mise en place des classes peut être une bonne chose à long terme en termes de découplage de votre code et de facilité de maintenance.

Adaptation du modèle d'usine

La mise en œuvre de l'usine peut varier considérablement par rapport à ce qui est présenté ici. Tenez compte des ajustements suivants lorsque vous créez votre propre modèle d'usine :

Utiliser un dictionnaire pour rechercher des produits : Il se peut que vous souhaitiez stocker vos produits sous forme de paires clé-valeur dans un dictionnaire. Utilisez un identifiant unique (par exemple, le nom ou un autre identifiant) comme clé et le type comme valeur. Cela peut faciliter la recherche des produits et/ou des usines correspondantes.

Rendre l'usine (ou un directeur d'usine) statique : Cela facilite son utilisation mais nécessite une configuration supplémentaire. Les classes statiques n'apparaîtront pas dans l'inspecteur, vous devrez donc également rendre votre collection de produits statique.

L'appliquer aux objets qui ne sont pas des objets de jeu et aux comportements qui ne sont pas des mono-comportements : Ne vous limitez pas aux préfabriqués ou à d'autres composants spécifiques à l'unité. Le modèle d'usine peut fonctionner avec n'importe quel objet C#.

Combinez avec le modèle de pool d'objets : Les usines n'ont pas nécessairement besoin d'instancier ou de créer de nouveaux objets. Ils peuvent également récupérer des documents existants dans la hiérarchie. Si vous instanciez de nombreux objets à la fois (par exemple, les projectiles d'une arme), utilisez le modèle de pool d'objets pour une gestion plus optimisée de la mémoire.

Les usines peuvent produire n'importe quel élément de jeu en fonction des besoins. Cependant, la création de produits n'est souvent pas leur seule raison d'être. Vous pouvez utiliser le modèle de fabrique dans le cadre d'une autre tâche plus importante (par exemple, la mise en place d'éléments d'interface utilisateur dans une boîte de dialogue de parties d'un niveau de jeu).

Article de blog
Plus de ressources

Vous trouverez d'autres conseils sur la manière d'utiliser les modèles de conception dans vos applications Unity, ainsi que les principes SOLID, dans l'e-book gratuit Level up your code with game programming patterns.

Vous pouvez trouver tous les livres électroniques et articles techniques avancés sur Unity dans le centre des meilleures pratiques. Les livres électroniques sont également disponibles sur la page des meilleures pratiques avancées dans la documentation.

Vous avez aimé ce contenu ?