« Salut Amigo ! »

"Salut, Bilaabo !"

"Notre sujet d'aujourd'hui ne sera pas seulement intéressant, il sera carrément épique."

« Aujourd'hui, je vais vous expliquer ce que sont les modèles de conception. »

« Cool ! J'en ai beaucoup entendu parler. J'ai hâte !

"Les programmeurs expérimentés doivent écrire de nombreuses classes. Mais la partie la plus difficile de ce travail consiste à décider quelles classes créer et comment répartir le travail entre elles."

"Plus ils résolvaient de telles questions, plus ils réalisaient que certaines solutions sont bonnes, tandis que d'autres sont mauvaises."

"Les mauvaises solutions créent généralement plus de problèmes qu'elles n'en résolvent. Elles s'étendent mal, créent de nombreuses limitations inutiles, etc. Et les bonnes solutions sont le contraire."

« Y a-t-il une analogie que vous pouvez faire ?

"Disons que vous construisez une maison. Et vous pensez à ce dont elle sera faite. Vous décidez que vous avez besoin de murs, d'un sol et d'un plafond. En conséquence, vous construisez une maison avec un toit plat et aucun Une telle maison se fissurera et le toit fuira. C'est une mauvaise solution.

"A l'inverse, une maison composée d'une fondation, de murs et d'un toit à pignon serait une bonne solution. Les fortes chutes de neige ne posent aucun problème, puisque la neige glissera du toit. Et les sols mouvants ne sont pas à craindre, car la fondation assurera stabilité. Nous appellerions une telle solution bonne.

"Je vois. Merci."

"OK. Alors je vais continuer."

"Avec le temps, les bonnes solutions sont devenues des modèles de conception, tandis que les mauvaises étaient appelées des anti-modèles."

"Un modèle de conception est comme une réponse à une question. C'est difficile à comprendre si vous n'avez jamais entendu la question."

" La première catégorie de modèles est celle des modèles de création. De tels modèles décrivent de bonnes solutions liées à la création d'objets. "

"Qu'y a-t-il de si compliqué dans la création d'objets ?"

"En l'occurrence, c'est exactement ce que nous allons explorer maintenant."

Motif singleton.

Design patterns : singleton, factory, factory method, abstract factory - 1

"Souvent, dans les programmes, une seule copie de certains objets peut exister. Par exemple, la console, l'enregistreur, le ramasse-miettes, etc."

" Mauvaise solution : ne créez aucun objet — créez simplement une classe dont les méthodes sont toutes statiques."

" Bonne solution :  créer un seul objet et le stocker dans une variable statique. Empêcher la création d'un second objet de la classe. Par exemple :"

Exemple
class Sun
{
 private static Sun instance;
 public static Sun getInstance()
 {
  if (instance == null)
  instance = new Sun();

  return instance;
 }

 private Sun()
 {
 }
}
Comment ça s'appelle
Sun sun = Sun.getInstance();

"C'est simple."

"Tout d'abord, nous rendons le constructeur privé. Désormais, il ne peut être appelé que depuis l'intérieur de notre classe. Nous avons bloqué la création d'objets Sun partout, sauf dans les méthodes de la classe Sun."

"Deuxièmement, un objet de cette classe ne peut être obtenu qu'en appelant la méthode getInstance(). Non seulement c'est la seule méthode qui peut créer un objet Sun, mais elle garantit également qu'il n'y a qu'un seul objet de ce type."

"Je vois."

"Quand vous pensez, "Maintenant, comment est-ce que je ferais exactement?", un modèle dit, "vous pouvez essayer ceci - c'est l'une des meilleures solutions.""

"Merci. Maintenant, les choses commencent à devenir claires."

"Vous pouvez également lire sur ce modèle  ici ."

Modèle d'usine.

Design patterns : singleton, factory, factory method, abstract factory - 2

"Voici une situation à laquelle les programmeurs sont très souvent confrontés. Vous avez une classe de base et de nombreuses sous-classes. Par exemple, une classe de personnage de jeu (GamePerson) et des classes pour tous les autres personnages qui en héritent."

"Disons que vous avez les classes suivantes :"

Exemple
abstract class GamePerson
{
}

class Warrior extends GamePerson
{
}

class Mag extends GamePerson
{
}

class Troll extends GamePerson
{
}

class Elf extends GamePerson
{
}

"La question est de savoir comment gérer de manière flexible et pratique la création d'objets de ces classes."

"Si ce problème vous semble tiré par les cheveux, imaginez que dans le jeu, vous devez créer des dizaines d'épées et de boucliers, des centaines de sorts magiques et des milliers de monstres. Vous ne pouvez pas vous passer d'une approche pratique de la création d'objets ici. "

"Le motif Factory offre une bonne solution."

"Tout d'abord, nous devons créer une énumération dont les valeurs correspondent aux différentes classes."

"Deuxièmement, créez une classe Factory spéciale qui a des méthodes statiques qui créent des objets basés sur une valeur enum."

"Par exemple:"

Exemple
public enum PersonType
{
 UNKNOWN,
 WARRIOR,
 MAG,
 TROLL,
 ELF,
}

public class PersonFactory
{
 public static GamePerson createPerson(PersonType personType)
 {
  switch(personType)
  {
   WARRIOR:
   return new Warrior();
   MAG:
   return new Mag();
   TROLL:
   return new Troll();
   ELF:
   return new Elf();
   default:
   throw new GameException();
  }
 }
}
Comment ça s'appelle
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"En d'autres termes, nous avons créé une classe spéciale pour gérer la création d'objets ?"

"Ouais."

« Alors, quels avantages cela offre-t-il ? »

"Tout d'abord, dans cette classe, les objets peuvent être initialisés avec les données nécessaires."

"Deuxièmement, vous pouvez passer la valeur enum nécessaire entre les méthodes autant que vous le souhaitez afin de créer finalement l'objet souhaité."

"Troisièmement, le nombre de champs d'énumération ne doit pas nécessairement correspondre au nombre de classes. Il peut y avoir plusieurs types de caractères, mais peu de classes."

"Par exemple, un Mag & Warrior peut utiliser une classe (Humain), mais avec une force et des propriétés magiques différentes (arguments du constructeur)."

"Voici à quoi cela pourrait ressembler (pour plus de clarté, j'ai également ajouté des elfes noirs) :"

Exemple
public enum PersonType
{
 UNKNOWN,
 WARRIOR,
 MAG,
 TROLL,
 ELF,
 DARK_ELF
}

public class PersonFactory
{
 public static GamePerson createPerson(PersonType personType)
 {
  switch(personType)
  {
   WARRIOR:
   return new Human(10, 0); // Strength, magic
   MAG:
   return new Human(0, 10); // Strength, magic
   TROLL:
   OGR:
   return new Troll();
   ELF:
   return new Elf(true); // true – good, false – evil
   DARK_ELF:
   return new Elf(false); // true – good, false – evil
   default:
   throw new GameException();
  }
 }
}
Comment ça s'appelle
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"Dans l'exemple ci-dessus, nous n'avons utilisé que trois classes pour créer six types d'objets différents. C'est très pratique. De plus, nous avons toute cette logique concentrée dans une classe et une méthode."

"Maintenant, supposons que nous décidions de créer une classe distincte pour Ogre - nous modifions simplement quelques lignes de code ici, et non la moitié de l'application."

"Je suis d'accord. C'est une bonne solution."

"Et c'est de cela que je parle : les modèles de conception sont des collections de bonnes solutions."

"J'aimerais aussi savoir où les utiliser…"

"Ouais. Je suis d'accord, vous ne comprendrez pas tout de suite. Pourtant, il vaut mieux savoir et ne pas pouvoir faire que ne pas savoir et ne pas pouvoir faire. Voici un autre lien utile pour vous concernant ce patron : Patron d' usine "

"Oh merci."

" Modèle d'usine abstrait ."

"Parfois, lorsque vous avez beaucoup d'objets, l'idée de créer une usine pour les usines se présente. Une telle usine s'appelle une usine abstraite ."

"Où cela serait-il nécessaire ?!"

"Supposons que vous ayez plusieurs groupes d'objets identiques. C'est plus facile à montrer avec un exemple."

"Maintenant, disons que vous avez trois races dans votre jeu : les humains, les elfes et les démons. Et pour l'équilibre, chaque race a des guerriers, des archers et des mages. Un joueur ne peut créer que des objets appartenant à la race pour laquelle il joue. dans le jeu. Voici à quoi cela ressemblerait dans le code :"

Déclaration des classes de soldat
class Warrior
{
}
class Archer
{
}
class Mag
{
}
Humains
class HumanWarrior extends Warrior
{
}

class HumanArcher extends Archer
{
}

class HumanMag extends Mag
{
}
Elfes
class ElfWarrior extends Warrior
{
}

class ElfArcher extends Archer
{
}

class ElfMag extends Mag
{
}
Démons
class DaemonWarrior extends Warrior
{
}

class DaemonArcher extends Archer
{
}

class DaemonMag extends Mag
{
}

Et maintenant, créons les races, ou nous pourrions aussi les appeler des armées.

Armées
abstract class Army
{
 public Warrior createWarrior();
 public Archer createArcher();
 public Mag createMag();
}
Armée humaine
class HumanArmy extends Army
{
 public Warrior createWarrior()
 {
  return new HumanWarrior();
 }
 public Archer createArcher()
 {
  return new HumanArcher();
 }
 public Mag createMag()
 {
  return new HumanMag();
 }
}
Armée d'elfes
class ElfArmy extends Army
{
 public Warrior createWarrior()
 {
  return new ElfWarrior();
 }
 public Archer createArcher()
 {
  return new ElfArcher();
 }
 public Mag createMag()
 {
  return new ElfMag();
 }
}
Armée démoniaque
class DaemonArmy extends Army
{
 public Warrior createWarrior()
 {
  return new DaemonWarrior();
 }
 public Archer createArcher()
 {
  return new DaemonArcher();
 }
 public Mag createMag()
 {
  return new DaemonMag();
 }
}

« Mais comment l'utilises-tu ?

"Vous pouvez utiliser les classes Armée, Guerrier, Archer et Mage n'importe où dans le programme, et pour créer les objets nécessaires - passez simplement un objet de la sous-classe Armée souhaitée."

"Par exemple:"

Exemple
Army humans = new HumanArmy();
Army daemons = new DaemonArmy();

Army winner = FightSimulator.simulate(humans, daemons);

"Dans l'exemple ci-dessus, nous avons une classe qui simule des batailles entre différentes races (armées). Il vous suffit de passer deux objets Armée. La classe elle-même les utilise pour créer diverses troupes et mène des batailles virtuelles entre elles afin d'identifier le vainqueur. ."

"Je vois. Merci. Une approche vraiment intéressante."

"Une bonne solution, quoi que vous disiez."

"Ouais."

"Voici un autre bon lien sur le sujet :  Abstract factory pattern "