"Hej, Amigo!"

"Hej, Bilaabo!"

"Vores emne i dag vil ikke kun være interessant - det vil være direkte episk."

"I dag vil jeg fortælle dig, hvad designmønstre er. "

"Fedt! Jeg har hørt meget om dem. Jeg kan ikke vente!"

"Erfarne programmører skal skrive mange klasser. Men den sværeste del af dette job er at beslutte, hvilke klasser der skal oprettes, og hvordan de skal fordele arbejdet mellem dem."

"Jo mere de løste sådanne spørgsmål, jo mere indså de, at nogle løsninger er gode, mens andre er dårlige."

"Dårlige løsninger skaber som regel flere problemer, end de løser. De strækker sig dårligt, skaber mange unødvendige begrænsninger osv. Og gode løsninger er det modsatte."

"Er der en analogi, du kan lave?"

"Lad os sige, at du bygger et hus. Og du tænker på, hvad det skal være lavet af. Du beslutter dig for, at du har brug for vægge, et gulv og et loft. Som et resultat bygger du et hus med et fladt tag og ingen fundament. Sådan et hus vil revne, og taget vil lække. Det er en dårlig løsning."

"Omvendt ville et hus bestående af et fundament, vægge og et sadeltag være en god løsning. Kraftigt snefald giver ikke noget problem, da sneen vil glide af taget. Og skiftende jord er ikke noget at frygte, for fundamentet vil sikre stabilitet. Vi vil kalde en sådan løsning god."

"Jeg forstår det. Tak."

"OK. Så fortsætter jeg."

"Med tiden blev de gode løsninger kendt som designmønstre, mens de dårlige blev kaldt anti-mønstre."

"Et designmønster er som et svar på et spørgsmål. Det er svært at forstå, hvis du aldrig har hørt spørgsmålet."

" Den første kategori af mønstre er kreative mønstre. Sådanne mønstre beskriver gode løsninger relateret til skabelsen af ​​objekter."

"Hvad er så kompliceret ved at skabe objekter?"

"Som det sker, er det lige det, vi skal udforske nu."

Singleton mønster.

Designmønstre: singleton, fabrik, fabriksmetode, abstrakt fabrik - 1

"Ofte kan der i programmer kun eksistere en enkelt kopi af nogle objekter. F.eks. konsollen, loggeren, skraldeopsamleren osv."

" Dårlig løsning: opret ikke nogen objekter - bare opret en klasse, hvis metoder alle er statiske."

" God løsning:  opret et enkelt objekt og gem det i en statisk variabel. Forhindr oprettelsen af ​​et andet objekt i klassen. For eksempel:"

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

  return instance;
 }

 private Sun()
 {
 }
}
Hvordan det hedder
Sun sun = Sun.getInstance();

"Det er simpelt."

"Først gør vi konstruktøren privat. Nu kan den kun kaldes inde fra vores klasse. Vi har blokeret for oprettelse af Sun-objekter overalt undtagen inden for Sun-klassens metoder."

"For det andet kan et objekt af denne klasse kun opnås ved at kalde getInstance()-metoden. Ikke alene er dette den eneste metode, der kan skabe et Sun-objekt, den sikrer også, at der kun er et sådant objekt."

"Jeg ser."

"Når du tænker, "Nu, hvordan ville jeg gøre det?", siger et mønster, "du kan prøve dette - dette er en af ​​de bedste løsninger."

"Tak. Nu begynder tingene at blive klare."

"Du kan også læse om dette mønster  her ."

Fabriksmønster.

Designmønstre: singleton, fabrik, fabriksmetode, abstrakt fabrik - 2

"Her er en situation, som programmører oplever meget ofte. Du har en basisklasse og mange underklasser. For eksempel en spilkarakterklasse (GamePerson) og klasser for alle de andre karakterer, som arver den."

"Lad os sige, at du har følgende klasser:"

Eksempel
abstract class GamePerson
{
}

class Warrior extends GamePerson
{
}

class Mag extends GamePerson
{
}

class Troll extends GamePerson
{
}

class Elf extends GamePerson
{
}

"Spørgsmålet er, hvordan vi fleksibelt og bekvemt administrerer skabelsen af ​​objekter i disse klasser."

"Hvis dette problem virker langt ude for dig, så forestil dig, at du i spillet skal skabe snesevis af sværd og skjolde, hundredvis af magiske besværgelser og tusindvis af monstre. Du kan ikke undvære en bekvem tilgang til objektskabelse her. "

" Fabriksmønsteret tilbyder en god løsning."

"Først skal vi skabe en enum, hvis værdier svarer til de forskellige klasser."

"For det andet, opret en speciel Factory- klasse, der har statiske metoder, der skaber objekt(er) baseret på en enum-værdi."

"For eksempel:"

Eksempel
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();
  }
 }
}
Hvordan det hedder
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"Med andre ord oprettede vi en speciel klasse til at styre objektskabelse?"

"Ja."

"Så hvilke fordele giver dette?"

"For det første, i denne klasse, kan objekterne initialiseres med de nødvendige data."

"For det andet kan du videregive den nødvendige enum-værdi mellem metoder, så meget du vil, for i sidste ende at skabe det ønskede objekt."

"For det tredje behøver antallet af enum-felter ikke at svare til antallet af klasser. Der kan være mange typer tegn, men få klasser."

"For eksempel kan en Mag & Warrior bruge en klasse (Human), men med forskellige styrke og magiske egenskaber (konstruktørargumenter)."

"Sådan kan det se ud (for klarhedens skyld har jeg også tilføjet mørke elvere):"

Eksempel
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();
  }
 }
}
Hvordan det hedder
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"I eksemplet ovenfor brugte vi kun tre klasser til at skabe seks forskellige typer objekter. Dette er meget praktisk. Desuden har vi al denne logik koncentreret i én klasse og én metode."

"Antag nu, at vi beslutter os for at oprette en separat klasse til Ogre - vi ændrer simpelthen et par linjer kode her, og ikke halvdelen af ​​applikationen."

"Jeg er enig. Det er en god løsning."

"Og det er det, jeg taler om: Designmønstre er samlinger af gode løsninger."

"Jeg ville også ønske, jeg vidste, hvor jeg skulle bruge dem..."

"Jep. Jeg er enig, du vil ikke forstå med det samme. Alligevel er det bedre at vide og ikke kunne gøre end at ikke vide og ikke kunne gøre. Her er et andet nyttigt link til dig om dette mønster: Fabriksmønster "

"Åh tak."

" Abstrakt fabriksmønster ."

"Nogle gange, når man har mange genstande, opstår ideen om at skabe en fabrik til fabrikker. Sådan en fabrik kaldes en abstrakt fabrik ."

"Hvor skulle det her være nødvendigt?!"

"Antag, at du har flere grupper af identiske objekter. Dette er lettere at vise med et eksempel."

"Lad os nu sige, at du har tre racer i dit spil: mennesker, elvere og dæmoner. Og for balancen har hver race krigere, bueskytter og magikere. En spiller kan kun skabe objekter, der tilhører den race, han eller hun spiller for i spillet. Sådan ville det se ud i kode:"

Erklæring af soldaterklasser
class Warrior
{
}
class Archer
{
}
class Mag
{
}
Mennesker
class HumanWarrior extends Warrior
{
}

class HumanArcher extends Archer
{
}

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

class ElfArcher extends Archer
{
}

class ElfMag extends Mag
{
}
Dæmoner
class DaemonWarrior extends Warrior
{
}

class DaemonArcher extends Archer
{
}

class DaemonMag extends Mag
{
}

Og lad os nu skabe racerne, eller vi kunne også kalde dem hære.

Hære
abstract class Army
{
 public Warrior createWarrior();
 public Archer createArcher();
 public Mag createMag();
}
Menneskelig hær
class HumanArmy extends Army
{
 public Warrior createWarrior()
 {
  return new HumanWarrior();
 }
 public Archer createArcher()
 {
  return new HumanArcher();
 }
 public Mag createMag()
 {
  return new HumanMag();
 }
}
Elver hær
class ElfArmy extends Army
{
 public Warrior createWarrior()
 {
  return new ElfWarrior();
 }
 public Archer createArcher()
 {
  return new ElfArcher();
 }
 public Mag createMag()
 {
  return new ElfMag();
 }
}
Dæmon hær
class DaemonArmy extends Army
{
 public Warrior createWarrior()
 {
  return new DaemonWarrior();
 }
 public Archer createArcher()
 {
  return new DaemonArcher();
 }
 public Mag createMag()
 {
  return new DaemonMag();
 }
}

"Men hvordan bruger du det her?"

"Du kan bruge klasserne Army, Warrior, Archer og Mage hvor som helst i programmet, og til at skabe de nødvendige objekter - bare gå forbi et objekt af den ønskede Army-underklasse."

"For eksempel:"

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

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

"I eksemplet ovenfor har vi en klasse, der simulerer kampe mellem forskellige racer (hære). Du skal bare passere to hærobjekter. Klassen selv bruger dem til at skabe forskellige tropper og udføre virtuelle kampe mellem dem for at identificere sejrherren ."

"Jeg forstår det. Tak. En virkelig interessant tilgang."

"En god løsning, uanset hvad du siger."

"Ja."

"Her er et andet godt link om emnet:  Abstrakt fabriksmønster "