Паттерн «Адаптер»
Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 51 из 65.
Шаблон Adapter позволяет объекту работать с кодом, который ожидает другие методы. Адаптер оборачивает объект и преобразует каждый ожидаемый вызов в вызов, понятный объекту.
Старый класс из более раннего проекта хранит здоровье в виде двух чисел:
# old_monster.gd
class_name OldMonster
extends RefCounted
var life := 30
var max_life := 120В вашем HUD отображается всё, у чего есть get_label() и get_hp_percent(). У Knight уже есть оба метода (он возвращает "Knight" и 80), а у OldMonster нет ни одного:
# health_display.gd
class_name HealthDisplay
extends RefCounted
func show_health(target) -> void:
print(target.get_label(), ": ", target.get_hp_percent(), "%")Адаптер хранит OldMonster и предоставляет два метода, которые вызывает отображение:
# monster_adapter.gd
class_name MonsterAdapter
extends RefCounted
var monster: OldMonster
func _init(wrapped: OldMonster) -> void:
monster = wrapped
func get_label() -> String:
return "Monster"
func get_hp_percent() -> int:
return monster.life * 100 / monster.max_life# main.gd
var display := HealthDisplay.new()
display.show_health(Knight.new())
display.show_health(MonsterAdapter.new(OldMonster.new()))Knight: 80%
Monster: 25%Не изменились ни OldMonster, ни HealthDisplay. Это важно, когда вы не можете или не должны редактировать класс: он поставляется с плагином, принадлежит другой команде или от его имён зависят многие скрипты.
Адаптер перенаправляет каждый вызов и преобразует данные по пути — здесь два числа в один процент. Умножай перед делением: при работе с целыми числами 30 / 120 * 100 равно 0, а 30 * 100 / 120 равно 25.
Задание
ЛегкоМетеостанция отображает датчики, у которых есть get_sensor_name() и get_celsius(), например ModernSensor (modern_sensor.gd). Станция находится в weather_board.gd. Старые термометры (legacy_thermometer.gd) предоставляют только read_fahrenheit() и get_code(). Напишите адаптер ThermometerAdapter:
- Конструктор сохраняет обёрнутый объект
LegacyThermometer. get_sensor_name()возвращаетThermometer, пробел и код термометра, напримерThermometer TH-4.get_celsius()возвращает температуру в градусах Цельсия:(fahrenheit - 32) * 5 / 9в видеfloat.
Не изменяйте остальные классы. Предоставленный код считывает количество следующих датчиков, а затем по одному датчику в каждой строке: legacy ID FAHRENHEIT или modern NAME CELSIUS. Он оборачивает каждый старый термометр в ваш адаптер и отображает все датчики. Для legacy 4 98.6 и modern Garden 21.5 вывод будет таким:
Thermometer TH-4: 37.0 C
Garden: 21.5 C
Warmest: Thermometer TH-4Ваш код поместите в thermometer_adapter.gd. В main.gd находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
extends Node
func _ready():
# Предоставленный код ввода-вывода: оставьте его без изменений
var board := WeatherBoard.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "legacy":
var old := LegacyThermometer.new(int(parts[1]), float(parts[2]))
board.add_sensor(ThermometerAdapter.new(old))
else:
board.add_sensor(ModernSensor.new(parts[1], float(parts[2])))
board.show_all()
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово selfМетодыСвойстваКонструктор (_init)Повторение: простой калькулятор4Полиморфизм
Переопределение методов: повторениеУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовПовторение — калькулятор фигур7Сигналы
Что такое сигнал?Объявление и отправкаПодключение к сигналамСигналы с аргументамиПовторение — система здоровья10Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»2Свойства классов
Переменные экземпляра и классаСтатические функцииСеттеры свойствГеттеры свойствПриватность по соглашениюПовторение — менеджер банковского счёта5Инкапсуляция
Открытые и закрытые членыПроверка данных с помощью сеттеровСокрытие информацииСвойства только для чтенияПовторение — система учета студентов8Продвинутые концепции ООП
Композиция и наследованиеВнутренние классыУзлы как компонентыRefCounted и NodeПеречисления в классах11Проект: Управление библиотекой
Обзор проектаКлассы книг и пользователей3Наследование
Основы наследованияКлючевое слово superПереопределение методовЦепочки наследованияПроверка типов с помощью isПовторение — иерархия сотрудников6Специальные методы
Введение в виртуальные методыМетод _to_stringПользовательские итераторыПовторение: пользовательский список9Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн «Одиночка»Паттерн «Фабрика»Паттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор GDScript