Какой это шаблон, и я должен это сделать?

9

Я делаю игру в as3, используя flash development и flash cs5. Все объектно-ориентировано. Мне было интересно, должен ли я иметь один класс "шлюза", который имеет ссылку на свойство для всех экземпляров других классов, и я просто передаю этот класс шлюза новым объектам, чтобы они имели доступ к каждому классу. Вот так:

 var block:Block = new Block(gateway);

 //In the block class:
 this.gateway.player.setHealth(100);
 //Or:
 this.gateway.input.lock();

Это как шаблон синглтона или что-то? Должен ли я сделать это?

тетрада
источник

Ответы:

13

Это называется шаблоном проектирования объекта контекста , и это лучше, чем шаблон синглтона.

  • Объекты контекста помогают в тестировании, потому что вы можете передавать фиктивные контексты функциям, которые хотите протестировать. Синглтоны мешают этому, потому что для того, чтобы издеваться над синглетонами, нужно, чтобы они не были одиночками.
  • Объекты контекста делают ваше «глобальное состояние» явным, и поэтому его легче рассуждать. Если функция не принимает объект контекста, вы знаете, что она не использует никакого глобального состояния контекста. У вас нет такой гарантии с одиночными или глобальными переменными.
  • Контекстные объекты будут немного медленнее, если вы их не используете, потому что вы добавляете другой параметр ко всем вызовам функций. Они могут быть быстрее глобальных, если вы их используете, и почти всегда быстрее, чем синглтоны.
  • Контекстные объекты легче реализовать; обычно они живут в куче или складываются обычным образом. У синглетонов есть сложные проблемы, связанные с многопоточностью на многих языках.

Так что нет, это не синглтон, это лучше, чем синглтон.

Тем не менее, вы по-прежнему обмениваетесь дурацким состоянием - тот факт, что вы храните все это в одной локальной переменной, делает ее более явной, но все же создает серьезную путаницу проблем . Имейте в виду одно правило ответственности . Имеет смысл иметь контекст, который владеет плеером и текущим уровнем - они связаны - но почему тот же контекст владеет вашим вводом с клавиатуры?

Рассмотрим разные уровни контекстов, например:

  • GameplayContext - владеет игроком, врагами, геометрией уровня и т. Д.
  • InputContext - владеет ручками клавиатуры и мыши, событиями ввода и т. Д.
  • GraphicsContext - владеет текстурами, дескриптором окна и т. Д.
  • GlobalContext - владеет GameplayContext, GraphicsContext и InputContext. Здесь вы хотите применить шаблон локатора службы , чтобы иметь возможность заменять одни контексты на другие при необходимости. И, может быть, для быстрой итерации и тестирования это должно быть в реальной глобальной переменной - просто поймите, что всякий раз, когда вы ее используете, вы создаете технический долг .

Эти контексты все еще несколько связывают опасения - возможно, какой-то обработчик события берет GameplayContext и действительно нуждается только в игроке - но обязанности четко определены. Вы знаете, что то, что занимает GameplayContext, не будет загружать текстуру; что-то, принимающее InputContext, не может убить игрока.

сообщество
источник
+1 Хороший ответ. Однако некоторые проблемы со скоростью или многопоточностью на самом деле не применимы в этом контексте (ActionScript3 не поддерживает многопоточность, и многие механизмы повышения скорости, которые работают в C ++, не применяются при использовании AS3).
Bummzack
Я не очень разбираюсь в AS3VM, но в большинстве динамических языков стоимость передачи / получения / использования локального по-прежнему выше (поиск по массиву), чем стоимость поиска по глобальному (поиск по хешу), и намного быстрее, чем вызов функции (дерьмо) для достижения цели. Поэтому я думаю, что этот совет все еще применяется.
0

Это не похоже на паттерн Синглтона. Насколько я понимаю, вы передаете объект со ссылками на важные игровые объекты всем своим экземплярам.

Если бы это был шаблон Singleton, вы бы имели:

AudioManager.getInstance().playSound(XY);

Тогда как в вашем случае вы могли бы иметь:

this.gateway.getAudioManager().playSound(XY);

Это выглядит в основном так же, но на самом деле это не так. Если вы хотите заменитьAudioManager на новый (расширенный класс), как ExtendedAudioManager, вы бы попали в стену, используя шаблон Singleton. Ваш подход к шлюзу справится с этим просто отлично.

Недостаток вашего подхода в том, что вам придется обойтись gatewayповсюду. Шаблон локатора службы (предложенный Джо Wreschnig в этой теме), выглядит как замена хорошей для вашего «шаблона шлюза».

Иногда лучше просто работать с простым и понятным методом, а не с чрезмерным дизайном. Особенно, когда это маленький проект или прототип. Может быть, вы могли бы сделать этоgateway своего рода глобальной переменной .. например. Game.gatewayи беги с этим.

bummzack
источник
-2

Большинство решений этой проблемы, включая паттерн Синглтона, включают использование статических переменных. Если у вас когда-либо будет только один игрок, вы можете просто указать Player как одноэлементный класс, что означает, что вы можете получить доступ к экземпляру Player через что-то вроде Player.currentPlayer. Однако многие люди злятся на синглетонов. Вы также можете иметь ResourceManager или аналогичный класс, который содержит статические ссылки на различные полезные глобальные переменные или довольно-таки чертовски глобальные переменные. В вашем коде вы также можете сделать статически доступными переменные «Gateway» вместо того, чтобы раздувать ваш код, передавая его повсюду.

Грегори Эйвери-Вейр
источник
Вопрос существенно изменился с тех пор, как я сделал этот ответ, настолько, что его редактировать не стоит.
Грегори Эйвери-Вейр
2
Кроме названия ничего не изменилось в вопросе.
bummzack
1
Какая? Ничего не изменилось, кроме названия. -1
AttackingHobo
Я думаю, что я думал о названии здесь; Я помню, что оригинальное название было что-то вроде "Как мне это сделать?" Вполне возможно, что я неправильно прочитал первоначальный заголовок / вопрос, когда сделал ответ.
Грегори Эйвери-Вейр