„Hallo, Amigo!“

„Hallo, Bilaabo!“

„Unser heutiges Thema wird nicht nur interessant sein, es wird geradezu episch sein.“

„Heute erkläre ich Ihnen, was Designmuster sind.

„Cool! Ich habe viel über sie gehört. Ich kann es kaum erwarten!“

„Erfahrene Programmierer müssen viele Klassen schreiben. Der schwierigste Teil dieser Arbeit besteht jedoch darin, zu entscheiden, welche Klassen erstellt werden sollen und wie die Arbeit auf diese aufgeteilt werden soll.“

„Je mehr sie solche Fragen lösten, desto klarer wurde ihnen, dass einige Lösungen gut und andere schlecht sind.“

„Schlechte Lösungen schaffen in der Regel mehr Probleme als sie lösen. Sie erstrecken sich schlecht, schaffen viele unnötige Einschränkungen usw. Und gute Lösungen sind das Gegenteil.“

„Gibt es eine Analogie, die Sie ziehen können?“

„Nehmen wir an, Sie bauen ein Haus. Und Sie denken darüber nach, woraus es bestehen soll. Sie entscheiden, dass Sie Wände, einen Boden und eine Decke brauchen. Als Ergebnis bauen Sie ein Haus mit einem Flachdach und nein Fundament. Ein solches Haus wird reißen und das Dach wird undicht. Das ist eine schlechte Lösung.“

„Umgekehrt wäre ein Haus, bestehend aus Fundament, Mauern und Satteldach, eine gute Lösung. Starker Schneefall stellt kein Problem dar, da der Schnee vom Dach rutscht. Und wechselnde Böden sind nicht zu befürchten, denn dafür sorgt das Fundament.“ Stabilität. Eine solche Lösung würden wir als gut bezeichnen.“

"Ich verstehe, danke."

„OK. Dann mache ich weiter.“

„Mit der Zeit wurden die guten Lösungen als Entwurfsmuster bekannt, während die schlechten als Anti-Muster bezeichnet wurden.“

„Ein Designmuster ist wie eine Antwort auf eine Frage. Es ist schwer zu verstehen, wenn man die Frage noch nie gehört hat.“

Die erste Kategorie von Mustern sind Erstellungsmuster. Solche Muster beschreiben gute Lösungen im Zusammenhang mit der Erstellung von Objekten.“

„Was ist so kompliziert am Erstellen von Objekten?“

„Das ist genau das, was wir jetzt erforschen werden.“

Singleton-Muster.

Entwurfsmuster: Singleton, Fabrik, Fabrikmethode, abstrakte Fabrik – 1

„Oft kann in Programmen nur eine einzige Kopie einiger Objekte existieren. Zum Beispiel die Konsole, der Logger, der Garbage Collector usw.“

Schlechte Lösung: Erstellen Sie keine Objekte – erstellen Sie einfach eine Klasse, deren Methoden alle statisch sind.“

Gute Lösung:  Erstellen Sie ein einzelnes Objekt und speichern Sie es in einer statischen Variablen. Verhindern Sie die Erstellung eines zweiten Objekts der Klasse. Zum Beispiel:“

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

  return instance;
 }

 private Sun()
 {
 }
}
Wie es heißt
Sun sun = Sun.getInstance();

"Es ist einfach."

„Zuerst machen wir den Konstruktor privat. Jetzt kann er nur noch innerhalb unserer Klasse aufgerufen werden. Wir haben die Erstellung von Sun-Objekten überall blockiert, außer innerhalb von Methoden der Sun-Klasse.“

„Zweitens kann ein Objekt dieser Klasse nur durch Aufrufen der Methode getInstance() abgerufen werden. Dies ist nicht nur die einzige Methode, die ein Sun-Objekt erstellen kann, sondern stellt auch sicher, dass es nur ein solches Objekt gibt.“

"Ich verstehe."

„Wenn Sie denken: „Wie genau würde ich das machen?“, sagt ein Muster: „Sie können das versuchen – das ist eine der besten Lösungen.“

„Danke. Jetzt wird es langsam klarer.“

„Über dieses Muster können Sie auch  hier lesen .“

Fabrikmuster.

Entwurfsmuster: Singleton, Fabrik, Fabrikmethode, abstrakte Fabrik – 2

„Hier ist eine Situation, mit der Programmierer sehr oft konfrontiert sind. Sie haben eine Basisklasse und viele Unterklassen. Zum Beispiel eine Spielcharakterklasse (GamePerson) und Klassen für alle anderen Charaktere, die sie erben.“

„Nehmen wir an, Sie haben die folgenden Klassen:“

Beispiel
abstract class GamePerson
{
}

class Warrior extends GamePerson
{
}

class Mag extends GamePerson
{
}

class Troll extends GamePerson
{
}

class Elf extends GamePerson
{
}

„Die Frage ist, wie wir die Erstellung von Objekten dieser Klassen flexibel und komfortabel bewältigen können.“

„Wenn Ihnen dieses Problem weit hergeholt erscheint, stellen Sie sich vor, dass Sie im Spiel Dutzende von Schwertern und Schilden, Hunderte von Zaubersprüchen und Tausende von Monstern erstellen müssen. Auf einen bequemen Ansatz zur Objekterstellung können Sie hier nicht verzichten. "

„Das Factory- Muster bietet eine gute Lösung.“

„Zuerst müssen wir eine Aufzählung erstellen, deren Werte den verschiedenen Klassen entsprechen.“

„Zweitens erstellen Sie eine spezielle Factory- Klasse mit statischen Methoden, die Objekte basierend auf einem Enumerationswert erstellen.“

"Zum Beispiel:"

Beispiel
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();
  }
 }
}
Wie es heißt
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

„Mit anderen Worten, wir haben eine spezielle Klasse erstellt, um die Objekterstellung zu verwalten?“

"Ja."

„Welche Vorteile bietet das?“

„Zuerst können in dieser Klasse die Objekte mit den notwendigen Daten initialisiert werden.“

„Zweitens können Sie den benötigten Enum-Wert beliebig oft zwischen Methoden übergeben, um letztendlich das gewünschte Objekt zu erstellen.“

„Drittens muss die Anzahl der Enum-Felder nicht mit der Anzahl der Klassen übereinstimmen. Es kann viele Arten von Zeichen geben, aber nur wenige Klassen.“

„Zum Beispiel könnte ein Mag und ein Krieger eine Klasse (Mensch) verwenden, aber mit unterschiedlicher Stärke und magischen Eigenschaften (Konstruktorargumente).“

„So könnte es aussehen (der Übersichtlichkeit halber habe ich auch Dunkelelfen hinzugefügt):“

Beispiel
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();
  }
 }
}
Wie es heißt
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

„Im obigen Beispiel haben wir nur drei Klassen verwendet, um sechs verschiedene Objekttypen zu erstellen. Das ist sehr praktisch. Darüber hinaus haben wir die gesamte Logik in einer Klasse und einer Methode konzentriert.“

„Angenommen, wir beschließen nun, eine separate Klasse für Ogre zu erstellen – wir ändern hier einfach ein paar Codezeilen und nicht die halbe Anwendung.“

„Ich stimme zu. Das ist eine gute Lösung.“

„Und genau das meine ich: Designmuster sind Sammlungen guter Lösungen.“

„Außerdem wünschte ich, ich wüsste, wo ich sie verwenden kann …“

„Ja. Ich stimme zu, Sie werden es nicht sofort verstehen. Dennoch ist es besser, es zu wissen und es nicht tun zu können, als es nicht zu wissen und es nicht tun zu können. Hier ist ein weiterer nützlicher Link für Sie zu diesem Muster: Factory Pattern

"Oh Danke."

Abstraktes Fabrikmuster .“

„Manchmal, wenn man viele Objekte hat, drängt sich die Idee auf, eine Fabrik für Fabriken zu schaffen. Eine solche Fabrik nennt man abstrakte Fabrik .“

„Wo wäre das nötig?!“

„Angenommen, Sie haben mehrere Gruppen identischer Objekte. Das lässt sich leichter anhand eines Beispiels zeigen.“

„Nehmen wir an, Sie haben drei Rassen in Ihrem Spiel: Menschen, Elfen und Dämonen. Und aus Gründen des Gleichgewichts hat jede Rasse Krieger, Bogenschützen und Magier. Ein Spieler kann nur Objekte erstellen, die zu der Rasse gehören, für die er oder sie spielt im Spiel. So würde es im Code aussehen:"

Erklärung der Soldatenklassen
class Warrior
{
}
class Archer
{
}
class Mag
{
}
Menschen
class HumanWarrior extends Warrior
{
}

class HumanArcher extends Archer
{
}

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

class ElfArcher extends Archer
{
}

class ElfMag extends Mag
{
}
Dämonen
class DaemonWarrior extends Warrior
{
}

class DaemonArcher extends Archer
{
}

class DaemonMag extends Mag
{
}

Und jetzt erstellen wir die Rassen, oder wir könnten sie auch Armeen nennen.

Armeen
abstract class Army
{
 public Warrior createWarrior();
 public Archer createArcher();
 public Mag createMag();
}
Menschliche Armee
class HumanArmy extends Army
{
 public Warrior createWarrior()
 {
  return new HumanWarrior();
 }
 public Archer createArcher()
 {
  return new HumanArcher();
 }
 public Mag createMag()
 {
  return new HumanMag();
 }
}
Elfenarmee
class ElfArmy extends Army
{
 public Warrior createWarrior()
 {
  return new ElfWarrior();
 }
 public Archer createArcher()
 {
  return new ElfArcher();
 }
 public Mag createMag()
 {
  return new ElfMag();
 }
}
Dämonenarmee
class DaemonArmy extends Army
{
 public Warrior createWarrior()
 {
  return new DaemonWarrior();
 }
 public Archer createArcher()
 {
  return new DaemonArcher();
 }
 public Mag createMag()
 {
  return new DaemonMag();
 }
}

„Aber wie benutzt man das?“

„Sie können die Klassen Army, Warrior, Archer und Mage überall im Programm verwenden und zum Erstellen der erforderlichen Objekte einfach ein Objekt der gewünschten Army-Unterklasse übergeben.“

"Zum Beispiel:"

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

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

„Im obigen Beispiel haben wir eine Klasse, die Schlachten zwischen verschiedenen Rassen (Armeen) simuliert. Sie müssen nur zwei Armeeobjekte passieren. Die Klasse selbst verwendet sie, um verschiedene Truppen zu erstellen und führt virtuelle Schlachten zwischen ihnen durch, um den Sieger zu identifizieren ."

„Ich verstehe. Danke. Ein wirklich interessanter Ansatz.“

„Eine gute Lösung, egal was Sie sagen.“

"Ja."

„Hier ist ein weiterer guter Link zum Thema:  Abstraktes Fabrikmuster