Как связать две иерархии классов? Наверное, выраженный одним предложением, вопрос звучит дико. Попробую сформулировать понятнее.
Игра разделена на некое подобие модели и представления. Имеется базовый класс для всех материальных объектов в игре: SpaceObject, у него есть наследники: Planet, Star, Ship, Asteroid и т.д.. Пока оно все "живет" внутри этой самой модели - все хорошо. Но как только возникает необходимость отобразить объект - появляются проблемы.
Итак, в случае, если объект появляется в одной локации с игроком (есть соответствующее событие), необходимо создать его "alter ego" в виде GameObject игрового движка. Проблема в таком коде:void InitializeSpaceObject(SpaceObject spaceObject)
{
if (spaceObject is Star)
InitializeStar(spaceObject as Star);
else if (spaceObject is Planet)
InitializePlanet(spaceObject as Planet);
else if (spaceObject is AsteroidField)
InitializeAsteroidField(spaceObject as AsteroidField);
else
throw new UnknownSpaceObjectTypeException("Cannot initialize SpaceObject of type " + spaceObject.GetType().ToString() + ": unknown type.");
}
Понятное дело, такой код, как минимум, нарушает принцип подстановки Лисков, а вообще - просто неудобен в использовании и расширении. Но просто добавить ссылку на некий инициализатор объекта в классе SpaceObject нельзя - модель не должна ничего знать о движке и всей логики визуализации.
Как можно избавиться от этой вереницы if'ов или, по крайней мере, автоматизировать процесс поиска инициализатора для нужного типа объекта?
Ниже попробую изложить пару вариантов, которые мне пришли в голову - возможно они жизнеспособны?
1)Объявить таблицу "Тип" - "Инициализатор". Чему быть инициализатором - делегатом метода или полноценным классом, вопрос уже вторичный. Немного лучше, чем if'ы, но все равно как-то громоздко
2)Unity-стайл. Создать по обычному MonoBehaviour скрипту на каждый тип объекта. Каждый слушает событие появления объекта в локации. Внутри подписанного метода - одна проверка if (spaceObject is ThisScriptHandlingType) {код инициализации}. Что скажете про такой вариант?

21 Авг 2019 в 07:05
190 +1
0
Ответы
1

Опций решения данной проблемы несколько. Один из вариантов, который может быть элегантным и гибким, - использование шаблона проектирования "Фабрика".

Создайте интерфейс или абстрактный класс, например, SpaceObjectFactory, у которого будет метод CreateSpaceObject. Затем создайте конкретные фабрики для каждого типа SpaceObject (PlanetFactory, StarFactory, AsteroidFieldFactory и т.д.), которые будут реализовывать метод CreateSpaceObject и возвращать соответствующий объект типа SpaceObject.

При необходимости инициализации SpaceObject вызывайте метод InitializeSpaceObject, передавая объект фабрики, соответствующий типу SpaceObject. Таким образом, вы избавитесь от длинной цепочки if-else и сможете легко добавлять новые типы SpaceObject, просто создавая новую фабрику.

Этот подход поможет разделить логику создания объектов от их инициализации, делая код более удобным и расширяемым.

20 Апр 2024 в 13:07
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Название заказа не должно быть пустым
Введите email
Бесплатные доработки
Гарантированные бесплатные доработки
Быстрое выполнение
Быстрое выполнение от 2 часов
Проверка работы
Проверка работы на плагиат
Интересные статьи из справочника
Поможем написать учебную работу
Название заказа не должно быть пустым
Введите email
Доверьте свою работу экспертам
Разместите заказ
Наша система отправит ваш заказ на оценку 96 424 авторам
Первые отклики появятся уже в течение 10 минут
Прямой эфир