Диспетчер объектов? Шаблон проектирования

#java #oop

#java #ооп

Вопрос:

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

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

Это реальный шаблон проектирования? Если да, то как он называется? Любой недостаток.

Ответ №1:

Это часто используемый подход, и при разумном обращении он может быть очень полезным. Хотя некоторым людям они не нравятся и они называют их «классами Бога», на самом деле они не являются таковыми, если они правильно структурированы. Проблемы начинают возникать, если вы думаете об этом просто как о «классе, который содержит все», но если вы подумаете об информационной структуре, у вас все должно быть в порядке.

Давайте рассмотрим пример. Давайте назовем интересующий вас класс «Game». Это всегда хорошее место для начала, потому что оно представляет сущность реального мира. Игра должна знать о себе: игрок1, игрок2, карта, номер хода. Поместите методы в Game для доступа к ним. Это совершенно правильный и хороший дизайн. Тогда эти объекты, в свою очередь, будут знать кое-что о себе. Игрок будет знать имя, уровень навыка, оставшуюся энергию. Карта будет знать размер и рельеф на каждом квадрате. Если вам нужно знать об отдельном квадрате, тогда у вас есть класс Map, реализующий getSquare(x, y) . Квадрат знает, каков его тип местности.

Ключевым моментом является то, что вы передаете методу только те вещи, которые ему нужны. Метод, который вычисляет путь между двумя единицами, принимает Map в качестве своего аргумента. Вы не передаете ему игру и не позволяете ей извлекать карту.

Многие системы имеют подобные объекты. java.lang.Runtime является примером. Однако вы должны минимизировать их использование с помощью описанных выше методов.

Существует одно очень важное искушение, которого следует избегать. После того, как вы обнаружили, что ваш «главный» класс передается почти каждому методу, вы можете подумать: «Почему бы мне просто не сделать этот класс доступным для каждого метода, не используя его в качестве аргумента?». Таким образом, создаются синглтоны. Избегайте.

Комментарии:

1. Как насчет моего скриптового движка. У меня есть скрипт, который запускается во время определенных событий. Скажем, игрок получает удар, он запускает «onDamage.js » сценарий. Скрипту необходимо получить доступ к игроку (или, по крайней мере, иметь возможность вызывать player.giveDamage()), и он должен знать о карте (если рейнджер, получает меньше урона, если снаружи) и должен знать о противнике, наносящем удар (или, по крайней мере, enemy.getDamageModifiers()). Также скрипт должен будет получить эффекты изображения (или, по крайней мере, effectsEngine.displayEffect()), а также необходимо обновить HUD и т.д. Однако скрипт содержится в объекте player. Как бы вы это спроектировали?

2. Это совершенно другой вопрос, который я бы рекомендовал задавать отдельно.

3. Было бы неплохо, если бы вы могли добавить абзац об устранении зависимостей. Допустим, у меня есть класс A, которому нужны материалы из класса B или оба в зависимости друг от друга. Это очень сложно выполнить начальной загрузкой, особенно при использовании многопоточности. Какие шаблоны ООП могли бы предложить в качестве прочной основы для таких ситуаций ? Например, какие названия шаблонов всплывают у вас в голове?

Ответ №2:

То, что вы описываете, — это шаблон проектирования, скорее, анти-шаблон. Его иногда называют классом God, и его следует избегать.

Статья Википедии объясняет основную проблему с классом God. В частности, такой объект нарушил бы Закон Деметры. В основном он говорит, что не разговаривайте с незнакомцами. Все объекты, полученные из объекта God, будут незнакомыми, и лучше избегать отправки им сообщений / вызова методов.

Комментарии:

1. Спасибо за ссылку. Это не будут методы предоставления, просто объекты. Это была бы скорее общая фабрика, выдающая игровые объекты, или скорее коммуникационный «хаб», который позволяет объектам передавать другие объекты.

2. Какой хороший шаблон для объекта объектов, которые должны взаимодействовать друг с другом? Я думал о каком-то канале связи, но не уверен.

3. Я думаю, что объяснение DJClayworth хорошо сформулировано. В частности, «Ключевым моментом является ..» абзац.

Ответ №3:

Другой взгляд на это — по сравнению с ответами Уилла О и Джуна — заключается в том, что это старая добрая запись; не более и не менее. Является ли это правильным дизайнерским решением или экземпляром анти-шаблона «God class», зависит от обстоятельств. Я бы сказал, что это нормально, когда этот класс не делает всю вашу кодовую базу взаимно рекурсивной, и когда в этом классе практически нет фактического кода, только атрибуты экземпляра для ссылки на все остальные объекты.

Ответ №4:

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

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

Комментарии:

1. Я больше думал о том, что карта будет «masterObject.getPlayer ()», а проигрыватель может перейти «masterObject.GetMap ()»