Паттерн «Декоратор»
Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 52 из 65.
Паттерн Decorator добавляет объекту поведение, оборачивая его в другой объект с теми же методами. Каждая обёртка вызывает объект внутри себя и добавляет свою часть, а обёртки можно комбинировать в любом порядке.
# weapon.gd
class_name Weapon
extends RefCounted
func get_damage() -> int:
return 10
func describe() -> String:
return "Sword"Декоратор наследуется от Weapon, поэтому его можно использовать везде, где ожидается оружие, и он хранит оружие, которое оборачивает:
# fire_enchant.gd
class_name FireEnchant
extends Weapon
var inner: Weapon
func _init(wrapped: Weapon) -> void:
inner = wrapped
func get_damage() -> int:
return inner.get_damage() + 5
func describe() -> String:
return inner.describe() + " + Fire"SharpEnchant записывается так же, но его get_damage() возвращает inner.get_damage() * 2, а его describe() добавляет " + Sharp".
# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())Sword: 10
Sword + Fire + Sharp: 30Вызовы идут внутрь: SharpEnchant обращается к FireEnchant, а тот — к мечу. Меч возвращает 10, огонь увеличивает значение до 15, а острое зачарование удваивает его до 30. В обратном порядке, FireEnchant.new(SharpEnchant.new(Weapon.new())), урон равен 10 * 2 + 5, то есть 25.
Без декораторов для каждой комбинации потребовался бы собственный подкласс: FireSword, SharpSword, FireSharpSword и так далее. С ними два небольших класса охватывают все комбинации, а для нового зачарования нужен всего один дополнительный файл.
Задание
СреднеКофейня готовит напитки с помощью декораторов. Beverage (beverage.gd) объявляет cost() и description(); Espresso (espresso.gd, $3) и Tea (tea.gd, $2) уже написаны. Каждый декоратор хранит оборачиваемый напиток в inner (конструкторы уже написаны). Переопределите cost() и description() в:
Milk: стоит на1больше и добавляет+ Milkк описанию.Mocha: стоит на2больше и добавляет+ Mocha.Large: удваивает стоимость всего, что находится внутри, и ставитLargeперед описанием.
Предоставленный код считывает количество следующих заказов, а затем по одному заказу в каждой строке: напиток (espresso или tea) и добавки к нему, применяемые слева направо. Для espresso milk large и tea mocha milk вывод будет таким:
Large Espresso + Milk: $8
Tea + Mocha + Milk: $5Ваш код нужно поместить в milk.gd, mocha.gd и large.gd. В main.gd находится предоставленный код ввода/вывода, который нельзя редактировать.
Попробуйте сами
extends Node
func _ready():
# Предоставленный код ввода-вывода: оставьте его без изменений
var count := int(OS.read_string_from_stdin())
for i in count:
var words := OS.read_string_from_stdin().split(" ")
var drink: Beverage = Tea.new()
if words[0] == "espresso":
drink = Espresso.new()
for extra in words.slice(1):
match extra:
"milk":
drink = Milk.new(drink)
"mocha":
drink = Mocha.new(drink)
"large":
drink = Large.new(drink)
print("%s: $%d" % [drink.description(), drink.cost()])
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово selfМетодыСвойстваКонструктор (_init)Повторение: простой калькулятор4Полиморфизм
Переопределение методов: повторениеУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовПовторение — калькулятор фигур7Сигналы
Что такое сигнал?Объявление и отправкаПодключение к сигналамСигналы с аргументамиПовторение — система здоровья10Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»2Свойства классов
Переменные экземпляра и классаСтатические функцииСеттеры свойствГеттеры свойствПриватность по соглашениюПовторение — менеджер банковского счёта5Инкапсуляция
Открытые и закрытые членыПроверка данных с помощью сеттеровСокрытие информацииСвойства только для чтенияПовторение — система учета студентов8Продвинутые концепции ООП
Композиция и наследованиеВнутренние классыУзлы как компонентыRefCounted и NodeПеречисления в классах11Проект: Управление библиотекой
Обзор проектаКлассы книг и пользователей3Наследование
Основы наследованияКлючевое слово superПереопределение методовЦепочки наследованияПроверка типов с помощью isПовторение — иерархия сотрудников6Специальные методы
Введение в виртуальные методыМетод _to_stringПользовательские итераторыПовторение: пользовательский список9Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн «Одиночка»Паттерн «Фабрика»Паттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор GDScript