„Здрасти, Амиго!“

„Здравей, Билаабо!“

„Днешната ни тема няма да бъде просто интересна – тя ще бъде направо епична.“

„Днес ще ви кажа Howво представляват шаблоните за проектиране.

"Готино! Чувал съм много за тях. Нямам търпение!"

"Опитните програмисти трябва да напишат много класове. Но най-трудната част от тази работа е да решат кои класове да създадат и How да разпределят работата между тях."

„Колкото повече решаваха такива въпроси, толкова повече разбираха, че някои решения са добри, докато други са лоши.“

"Лошите решения обикновено създават повече проблеми, отколкото разрешават. Те се разширяват лошо, създават много ненужни ограничения и т.н. А добрите решения са обратното."

— Има ли няHowва аналогия, която можеш да направиш?

„Да кажем, че строите къща. И мислите от Howво ще бъде напequalsа. Решавате, че имате нужда от стени, под и таван. В резултат на това строите къща с плосък покрив и без основа. Такава къща ще се напука и покривът ще протече. Това е лошо решение."

„Обратно, къща, състояща се от основа, стени и двускатен покрив, би била добро решение. Обилният снеговалеж не представлява проблем, тъй като снегът ще се свлече от покрива. И не трябва да се страхувате от разместващи се почви, защото основата ще гарантира стабилност. Бихме нарекли такова решение добро."

— Разбирам. Благодаря.

"Добре. Тогава ще продължа."

„С времето добрите решения станаха известни като дизайнерски модели, докато лошите бяха наречени анти-модели.“

"Моделът на проектиране е като отговор на въпрос. Трудно е да разберете, ако никога не сте чували въпроса."

" Първата категория модели са модели за създаване. Такива модели описват добри решения, свързани със създаването на обекти."

"Какво е толкова сложно в създаването на обекти?"

„Както се случи, точно това ще проучим сега.“

Единичен модел.

Шаблони за проектиране: сингълтон, фабрика, фабричен метод, абстрактна фабрика - 1

„Често в програмите може да съществува само едно копие на някои обекти. Например конзолата, регистраторът, събирачът на боклука и т.н.“

" Лошо решение: не създавайте ниHowви обекти - просто създайте клас, чиито методи са статични."

" Добро решение:  създайте един обект и го съхранете в статична променлива. Предотвратете създаването на втори обект от класа. Например:"

Пример
class Sun
{
 private static Sun instance;
 public static Sun getInstance()
 {
  if (instance == null)
  instance = new Sun();

  return instance;
 }

 private Sun()
 {
 }
}
Как се казва
Sun sun = Sun.getInstance();

"Просто е."

"Първо, правим конструктора частен. Сега той може да бъде извикан само от нашия клас. Блокирахме създаването на обекти Sun навсякъде, освен в методите на класа Sun."

„Второ, обект от този клас може да бъде получен само чрез извикване на метода getInstance(). Това не само е единственият метод, който може да създаде обект Sun, но също така гарантира, че има само един такъв обект.“

"Виждам."

„Когато си помислите, „Как точно бих направил това?“, модел казва, „можете да опитате това – това е едно от най-добрите решения.““

„Благодаря. Сега нещата започват да се изясняват.“

„Можете също да прочетете за този модел  тук .“

Фабрична шарка.

Шаблони за проектиране: сингълтон, фабрика, фабричен метод, абстрактна фабрика - 2

„Ето ситуация, с която програмистите се сблъскват много често. Имате няHowъв базов клас и много подкласове. Например, клас на игрови герои (GamePerson) и класове за всички останали герои, които го наследяват.“

„Да приемем, че имате следните класове:“

Пример
abstract class GamePerson
{
}

class Warrior extends GamePerson
{
}

class Mag extends GamePerson
{
}

class Troll extends GamePerson
{
}

class Elf extends GamePerson
{
}

„Въпросът е How да управляваме гъвкаво и удобно създаването на обекти от тези класове.“

„Ако този проблем ви изглежда пресилен, представете си, че в играта трябва да създадете десетки мечове и щитове, стотици магически заклинания и хиляди чудовища. Тук не можете да правите без удобен подход за създаване на обекти. "

Фабричният модел предлага добро решение.“

„Първо, трябва да създадем enum, чиито стойности съответстват на различните класове.“

„Второ, създайте специален Factory клас, който има статичен метод(и), който създава обект(и) въз основа на enum стойност.“

"Например:"

Пример
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();
  }
 }
}
Как се казва
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

„С други думи, създадохме специален клас за управление на създаването на обекти?“

— Да.

„И така, Howви предимства предоставя това?“

"Първо, в този клас обектите могат да бъдат инициализирани с необходимите данни."

„Второ, можете да предавате необходимата стойност на enum между методите, колкото желаете, за да създадете в крайна сметка желания обект.“

"Трето, броят на полетата enum не трябва да съвпада с броя на класовете. Може да има много типове знаци, но малко класове."

„Например, Mag & Warrior може да използва един клас (Human), но с различна сила и магически свойства (аргументи на конструктора).“

„Ето How може да изглежда (за по-голяма яснота, добавих и тъмни елфи):“

Пример
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();
  }
 }
}
Как се казва
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"В горния пример използвахме само три класа, за да създадем шест различни типа обекти. Това е много удобно. Освен това имаме цялата тази логика, концентрирана в един клас и един метод."

„Да предположим сега, че решим да създадем отделен клас за Ogre – ние просто променяме няколко реда code тук, а не половината приложение.“

"Съгласен съм. Това е добро решение."

„И това е, за което говоря: моделите на дизайн са колекции от добри решения.“

„Също така ми се иска да знаех къде да ги използвам…“

"Да. Съгласен съм, няма да разберете веднага. Все пак е по-добре да знаете и да не можете да направите, отколкото да не знаете и да не можете да направите. Ето още една полезна връзка за вас относно този модел: Фабричен шаблон "

"О благодаря."

" Абстрактен фабричен модел."

"Понякога, когато имате много обекти, идеята за създаване на фабрика за фабрики се предлага сама по себе си. Такава фабрика се нарича абстрактна фабрика ."

"Къде ще е необходимо това?!"

"Да предположим, че имате няколко групи идентични обекти. Това е по-лесно да се покаже с пример."

„А сега да кажем, че имате три раси в играта си: хора, елфи и демони. И за баланс всяка раса има воини, стрелци и магове. Играчът може да създава само обекти, принадлежащи на расата, за която играе в играта. Ето How ще изглежда в codeа:"

Декларация за класове войници
class Warrior
{
}
class Archer
{
}
class Mag
{
}
хора
class HumanWarrior extends Warrior
{
}

class HumanArcher extends Archer
{
}

class HumanMag extends Mag
{
}
Елфи
class ElfWarrior extends Warrior
{
}

class ElfArcher extends Archer
{
}

class ElfMag extends Mag
{
}
Демони
class DaemonWarrior extends Warrior
{
}

class DaemonArcher extends Archer
{
}

class DaemonMag extends Mag
{
}

А сега нека създадем расите or можем да ги наречем и армии.

армии
abstract class Army
{
 public Warrior createWarrior();
 public Archer createArcher();
 public Mag createMag();
}
Човешка армия
class HumanArmy extends Army
{
 public Warrior createWarrior()
 {
  return new HumanWarrior();
 }
 public Archer createArcher()
 {
  return new HumanArcher();
 }
 public Mag createMag()
 {
  return new HumanMag();
 }
}
Армия на елфите
class ElfArmy extends Army
{
 public Warrior createWarrior()
 {
  return new ElfWarrior();
 }
 public Archer createArcher()
 {
  return new ElfArcher();
 }
 public Mag createMag()
 {
  return new ElfMag();
 }
}
Демонска армия
class DaemonArmy extends Army
{
 public Warrior createWarrior()
 {
  return new DaemonWarrior();
 }
 public Archer createArcher()
 {
  return new DaemonArcher();
 }
 public Mag createMag()
 {
  return new DaemonMag();
 }
}

"Но How използвате това?"

„Можете да използвате класовете Army, Warrior, Archer и Mage навсякъде в програмата и за да създадете необходимите обекти – просто предайте обект от желания подклас Army.“

"Например:"

Пример
Army humans = new HumanArmy();
Army daemons = new DaemonArmy();

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

„В примера по-горе имаме клас, който симулира битки между различни раси (армии). Просто трябва да преминете два армейски обекта. Самият клас ги използва, за да създава различни войски и провежда виртуални битки между тях, за да идентифицира победителя ."

„Разбирам. Благодаря. Наистина интересен подход.“

„Добро решение, независимо Howво казвате.

— Да.

"Ето още една добра връзка по темата:  Абстрактна фабрична шарка "