ООП: проектирование системы меню

В настоящее время я пытаюсь создать систему меню для игры и не могу найти какой-либо действительно надежный способ сделать это. Есть несколько экранов меню, каждый из которых нетривиальный, поэтому я хотел бы сохранить их как отдельные классы. Основная проблема, с которой я столкнулся, - это передача управления между этими экранами меню.

Я попытался построить каждый из экранов как синглтон и вызывать один экран напрямую с другого, т.е. что-то вроде [[MainMenu instance] display] в Objective C. Это немного беспорядочно, потому что (1) мне нужно написать шаблонный одноэлементный код для каждого из экранов меню и (2) классы становятся зависимыми друг от друга, иногда мне приходится кодировать по кругу зависимости и т. д.

Я подумал о том, чтобы сделать классы полностью статичными, чтобы обойти управление экземплярами (что в данном случае немного лишнее, поскольку на самом деле существует только один экземпляр каждого экрана). Но это также выглядит довольно некрасиво, особенно с учетом того, что Objective C вынужден «подделывать» переменные класса, объявляя их static.

Затем я подумал о каком-то классе «менеджера», который будет создавать экземпляры и передавать управление, но я не уверен, что введение дополнительного класса решит проблему, особенно если этот класс будет называться Manager :-)

Должен заметить, что у меня делать есть работающая система, просто не очень приятно. Под этим я подразумеваю, что происходит небольшое дублирование кода, если я не буду осторожен, вещь может зависнуть и так далее. Есть идеи? Я понимаю, что это недостаточно определено, так что обсуждение, вероятно, будет скорее мозговым штурмом, но меня все равно интересуют идеи, даже если они не решают полностью мою проблему.

Обновление: Спасибо всем за идеи. Что я в итоге сделал:

Я переработал содержимое меню (кнопки, графику и т. д.), Чтобы оно соответствовало одному интерфейсу под названием ScreenView. Это общий интерфейс, который выглядит так:

@protocol ScreenView

- (void) draw;
- (BOOL) handlesPoint: (CGPoint) p;

- (void) appearWithAnimation;
- (void) disappearWithAnimation;
- (BOOL) hasFinishedAnimating;

@optional

- (void) fingerDown;
- (void) fingerUp;

@end

Благодаря этому протоколу я смог отбросить все определенные экраны меню и создать общий экран меню, который принимает список подвидов для отображения и обрабатывает всю презентацию, такую ​​как рисование, переходы, события и т. д. Этот общий экран меню не подвергается частым подклассам, потому что большинство экранов меню просто отображают список подпредставлений. Это будет V в MVC.

Затем я также создал класс контроллера, который обрабатывает все события для определенного экрана меню. (Очевидно, C в MVC.) Класс корневого контроллера обрабатывает управление экземпляром, переходы между меню и некоторые другие мелочи. Большинство экранов меню получают настраиваемый подкласс контроллера, который обрабатывает события от кнопок и других подпредставлений.

Количество классов увеличилось, но код намного чище, не повторяется и менее подвержен ошибкам. Управление экземплярами все еще не идеально, но дизайн меня вполне устраивает. Еще раз спасибо всем, кто ответил.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
1 274
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, что класс MenuManager был бы подходящим вариантом. У вас будет один базовый класс Menu, от которого происходят все экраны меню, и у менеджера будет указатель на текущий активный экран меню. Он также может, например, отслеживать предыдущие экраны меню для удобного использования кнопок возврата на экранах меню при вызовах произвольных экранов меню. Возможно, просто используйте для этого std :: vector, чтобы вам не приходилось воссоздавать предыдущие экраны меню при возврате (это также предотвратит потерю введенной информации, как в меню параметров с подменю Advanced).

Помещение всего содержимого меню в словарь, сброс в список и чтение каждого по мере необходимости с экранов меню, вероятно, самый простой путь, но, честно говоря, вам следует подумать о более ориентированном на MVC подходе к решению проблемы. Экраны должны быть для представления данных, а не для их хранения. Если вы обеспечите четкое разделение данных и представлений, проблема решится сама собой.

Ответ принят как подходящий

Один из приемов, которым я научился для создания достойного дизайна, - всегда отделять данные от кода. Это сделает ЧУДЕСА для вашей конкретной проблемы.

Под этим я подразумеваю, что элементы меню (строки) и отношения между меню должны храниться где-то либо в массиве, либо в отдельном файле (и считываться в массив).

Затем вы используете этот массив для создания экземпляров всех классов меню.

Как только вы перекодируете его так, чтобы он работал таким образом (я сделал это с меню), весь ваш код встанет на свои места, вы также исключите - 90% вашего кода меню (каждое меню больше не будет собственным классом , точно такой же класс, созданный с его собственными уникальными данными.

Цели пунктов меню также хранятся в «данных» (как указатели на методы или экземпляры классов).

Другие вопросы по теме