[Exemple] Strategy & Factory Method : un système de sort basique
Page 1 sur 1
[Exemple] Strategy & Factory Method : un système de sort basique
Dans ce sujet, je vais essayer de vous expliquez comment fonctionnent deux patterns dans le même exemple : Strategy et Factory Method.
Le code source se trouve ici : http://kidanger.ath.cx/DUT/Projet1A2A/test/spells.tar.
Je commence par expliquer le pattern Strategy.
La situation :
Comment implémenter les sorts dans un RPG ressemblant fortement à D&D ?
Première solution : l'héritage simple
Une classe (abstraite) Spell, dont hérite une classe FireballSpell et SelfhealSpell. Jusque là c'est pas trop compliqué.
Seulement, dans un jeu comme D&D, il y a environ 300 sorts. Bien, mais en 1 an, on va pas avoir le temps d'implémenter 300 sorts et plus de 100 monstres de cette manière.
Deuxième solution :
Or, il va y avoir plusieurs sorte de sorts de soin, plusieurs sorte de sorts de dégâts de feu.
De plus, il y a plusieurs sorte de sorts dont seul le lanceur est la cible.
On peut donc dire qu'un sort est constitué d'un comportement de sélection (qui étend SpellTarget, détermine quelles sont les cibles) et un comportement d'action (qui étend SpellAction, on réalise une action pour chaque cible).
Ici, j'ai implémenté SpellRayTarget (sélectionne les cibles en ligne droite) et SpellSelfTarget (sélectionne le lanceur du sort) pour les sélections. Concernant les actions, j'ai implémenté SpellHealAction (soigne les cibles) et SpellDamageAction (fait des dégâts aux cibles).
Ce sont les seuls comportements que j'ai implémenté dans l'exemple, mais on peut vite en imaginer d'autre.
Je n'explique pas plus, ça prendrait beaucoup de temps. Le code Java n'est pas le plus beau, et il manque de commentaires, mais c'est juste un exemple pour montrer l'utilité d'un tel système.
Concernant le pattern Factory Method, il s'agit d'une classe qui permet d'instancier une classe sans avoir à ce soucier de comment elle est instanciée.
Ici, je passe le paramètre "nom" à la méthode "create" d'une instance de SpellFactory (instance static, dans Player). Cette méthode me renvoie une instance de Spell, prête à être lancée par le joueur.
L'avantage est double : on peut instancier des sorts à partir de leur nom, sans salir le code. De plus, imaginons que les données des sorts (exemple : les dégâts, la portée) se trouvent dans une base de données. Grace à la fabrique de sort, la connexion à la base peut être réalisée une seul fois, dans le constructeur de SpellFactory. À chaque appel de "create", on peut imaginer qu'une requête ira interroger la base afin de piocher les informations nécessaires à l'instanciation du sort.
La solution des Design Pattern est plus compliquée à mettre en place. Mais une fois le système établi, il est aisé de créé de nouveaux sorts.
La phase de conception et de modélisation est ici très importante, car il faut savoir quels sont les comportements que l'on doit définir, en fonction de la liste des sorts.
Si je ne suis pas clair, ou si vous avez des questions, n'hésitez pas !
EDIT : il est vrai qu'à l'heure qu'il est, il ne faut pas commencer la conception, et encore moins la programmation. Mais c'est un premier test pour savoir si certains DP peuvent nous être utiles.
Le code source se trouve ici : http://kidanger.ath.cx/DUT/Projet1A2A/test/spells.tar.
Je commence par expliquer le pattern Strategy.
La situation :
Comment implémenter les sorts dans un RPG ressemblant fortement à D&D ?
Première solution : l'héritage simple
Une classe (abstraite) Spell, dont hérite une classe FireballSpell et SelfhealSpell. Jusque là c'est pas trop compliqué.
Seulement, dans un jeu comme D&D, il y a environ 300 sorts. Bien, mais en 1 an, on va pas avoir le temps d'implémenter 300 sorts et plus de 100 monstres de cette manière.
Deuxième solution :
Or, il va y avoir plusieurs sorte de sorts de soin, plusieurs sorte de sorts de dégâts de feu.
De plus, il y a plusieurs sorte de sorts dont seul le lanceur est la cible.
On peut donc dire qu'un sort est constitué d'un comportement de sélection (qui étend SpellTarget, détermine quelles sont les cibles) et un comportement d'action (qui étend SpellAction, on réalise une action pour chaque cible).
Ici, j'ai implémenté SpellRayTarget (sélectionne les cibles en ligne droite) et SpellSelfTarget (sélectionne le lanceur du sort) pour les sélections. Concernant les actions, j'ai implémenté SpellHealAction (soigne les cibles) et SpellDamageAction (fait des dégâts aux cibles).
Ce sont les seuls comportements que j'ai implémenté dans l'exemple, mais on peut vite en imaginer d'autre.
Je n'explique pas plus, ça prendrait beaucoup de temps. Le code Java n'est pas le plus beau, et il manque de commentaires, mais c'est juste un exemple pour montrer l'utilité d'un tel système.
Concernant le pattern Factory Method, il s'agit d'une classe qui permet d'instancier une classe sans avoir à ce soucier de comment elle est instanciée.
Ici, je passe le paramètre "nom" à la méthode "create" d'une instance de SpellFactory (instance static, dans Player). Cette méthode me renvoie une instance de Spell, prête à être lancée par le joueur.
L'avantage est double : on peut instancier des sorts à partir de leur nom, sans salir le code. De plus, imaginons que les données des sorts (exemple : les dégâts, la portée) se trouvent dans une base de données. Grace à la fabrique de sort, la connexion à la base peut être réalisée une seul fois, dans le constructeur de SpellFactory. À chaque appel de "create", on peut imaginer qu'une requête ira interroger la base afin de piocher les informations nécessaires à l'instanciation du sort.
La solution des Design Pattern est plus compliquée à mettre en place. Mais une fois le système établi, il est aisé de créé de nouveaux sorts.
La phase de conception et de modélisation est ici très importante, car il faut savoir quels sont les comportements que l'on doit définir, en fonction de la liste des sorts.
Si je ne suis pas clair, ou si vous avez des questions, n'hésitez pas !
EDIT : il est vrai qu'à l'heure qu'il est, il ne faut pas commencer la conception, et encore moins la programmation. Mais c'est un premier test pour savoir si certains DP peuvent nous être utiles.
Dernière édition par Jérémy le Sam 25 Fév - 10:52, édité 1 fois (Raison : URL pour les visiteur)
Jérémy- Analyste-programmeur
- Messages : 79
Feuille de personnage
Nom du personnage:
Diagramme de classe
Voici le diagramme de classe correspondant au code : http://kidanger.ath.cx/DUT/Projet1A2A/test/spells.png
Il n'est pas tout à fait exacte : dans le code on trouve une classe SpellChance (qui correspond à un lancé de dés, ou à une valeur fixe), qui sert aux Actions. Mais globalement, le principe de Factory et de Strategy se comprend par ce diagramme.
Il n'est pas tout à fait exacte : dans le code on trouve une classe SpellChance (qui correspond à un lancé de dés, ou à une valeur fixe), qui sert aux Actions. Mais globalement, le principe de Factory et de Strategy se comprend par ce diagramme.
Jérémy- Analyste-programmeur
- Messages : 79
Feuille de personnage
Nom du personnage:
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum