Читати книгу - "Занурення в патерни проектування, Олександр Швець"
Шрифт:
Інтервал:
Додати в закладку:
Абстрактний клас визначає кроки алгоритму й містить шаблонний метод, що складається з викликів цих кроків. Кроки можуть бути як абстрактними, так і містити реалізацію за замовчуванням.
Конкретний клас перевизначає деякі або всі кроки алгоритму. Конкретні класи не перевизначають сам шаблонний метод.
ПсевдокодУ цьому прикладі Шаблонний метод використовується як заготовка для стандартного штучного інтелекту в простій стратегічній грі. Для введення в гру нової раси достатньо створити підклас і реалізувати в ньому відсутні методи.
Приклад класів штучного інтелекту для простої гри.
Всі раси гри матимуть приблизно однакові типи юнітів та будівель, тому структура штучного інтелекту буде однаковою. Але різні раси можуть різним шляхом реалізувати ці кроки. Так, наприклад, орки будуть агресивнішими в атаці, люди більш активними в захисті, а дикі монстри взагалі не будуть займатися будівництвом.
class GameAI is// Шаблонний метод повинен бути заданий у базовому класі.
// Він складається з викликів методів у певному порядку.
// Здебільшого, ці методи є кроками якогось алгоритму.
method turn() is
collectResources()
buildStructures()
buildUnits()
attack()
// Деякі з цих методів можуть бути реалізовані безпосередньо
// у базовому класі.
method collectResources() is
foreach (s in this.builtStructures) do
s.collect()
// А деякі можуть бути повністю абстрактними.
abstract method buildStructures()
abstract method buildUnits()
// До речі, клас може мати більше одного шаблонного методу.
method attack() is
enemy = closestEnemy()
if (enemy == null)
sendScouts(map.center)
else
sendWarriors(enemy.position)
abstract method sendScouts(position)
abstract method sendWarriors(position)
// Підкласи можуть надавати свою реалізацію кроків алгоритму, не
// змінюючи сам шаблонний метод.
class OrcsAI extends GameAI is
method buildStructures() is
if (there are some resources) then
// Будувати ферми, потім бараки, а потім цитадель.
method buildUnits() is
if (there are plenty of resources) then
if (there are no scouts)
// Побудувати раба, додати до групи розвідників.
else
// Побудувати піхотинця, додати до групи воїнів.
// ...
method sendScouts(position) is
if (scouts.length > 0) then
// Відправити розвідників на позицію.
method sendWarriors(position) is
if (warriors.length > 5) then
// Відправити воїнів на позицію.
// Підкласи можуть не тільки реалізовувати абстрактні кроки, але
// й перевизначати кроки, вже реалізовані в базовому класі.
class MonstersAI extends GameAI is
method collectResources() is
// Нічого не робити.
method buildStructures() is
// Нічого не робити.
method buildUnits() is
// Нічого не робити. Застосування
Якщо підкласи повинні розширювати базовий алгоритм, не змінюючи його структури.
Шаблонний метод дозволяє підкласами розширювати певні кроки алгоритму через спадкування, не змінюючи при цьому структуру алгоритмів, оголошену в базовому класі.
Якщо у вас є кілька класів, які роблять одне й те саме з незначними відмінностями. Якщо ви редагуєте один клас, тоді доводиться вносити такі ж виправлення до інших класів.
Патерн шаблонний метод пропонує створити для схожих класів спільний суперклас та оформити в ньому головний алгоритм у вигляді кроків. Кроки, які відрізняються, можна перевизначити у підкласах.
Це дозволить прибрати дублювання коду в кількох класах, які відрізняються деталями, але мають схожу поведінку.
Кроки реалізаціїВивчіть алгоритм і подумайте, чи можна його розбити на кроки. Вирішіть, які кроки будуть стандартними для всіх варіацій алгоритму, а які можуть бути змінюваними.
Створіть абстрактний базовий клас. Визначте в ньому шаблонний метод. Цей метод повинен складатися з викликів кроків алгоритму. Є сенс у тому, щоб зробити шаблонний метод фінальним, аби підкласи не могли перевизначити його (якщо ваша мова програмування це дозволяє).
Додайте до абстрактного класу методи для кожного з кроків алгоритму. Ви можете зробити ці методи абстрактними або додати якусь типову реалізацію. У першому випадку всі підкласи повинні будуть реалізувати ці методи, а в другому — тільки якщо реалізація кроку в підкласі відрізняється від стандартної версії.
Подумайте про введення хуків в алгоритм. Найчастіше хуки розташовують між основними кроками алгоритму, а також до та після всіх кроків.
Створіть конкретні класи, успадкувавши їх від абстрактного класу. Реалізуйте в них всі кроки та хуки, яких не вистачає.
Переваги та недоліки Полегшує повторне використання коду. Ви жорстко обмежені скелетом існуючого алгоритму. Ви можете порушити принцип підстановки Барбари Лісков, змінюючи базову поведінку одного з кроків алгоритму через підклас. У міру зростання кількості кроків шаблонний метод стає занадто складно підтримувати. Відносини з іншими патернамиФабричний метод можна розглядати як окремий випадок Шаблонного методу. Крім того,
Увага!
Сайт зберігає кукі вашого браузера. Ви зможете в будь-який момент зробити закладку та продовжити читання книги «Занурення в патерни проектування, Олександр Швець», після закриття браузера.