Я делаю игру в as3, используя flash development и flash cs5. Все объектно-ориентировано. Мне было интересно, должен ли я иметь один класс "шлюза", который имеет ссылку на свойство для всех экземпляров других классов, и я просто передаю этот класс шлюза новым объектам, чтобы они имели доступ к каждому классу. Вот так:
var block:Block=newBlock(gateway);//In the block class:this.gateway.player.setHealth(100);//Or:this.gateway.input.lock();
Это как шаблон синглтона или что-то? Должен ли я сделать это?
Объекты контекста помогают в тестировании, потому что вы можете передавать фиктивные контексты функциям, которые хотите протестировать. Синглтоны мешают этому, потому что для того, чтобы издеваться над синглетонами, нужно, чтобы они не были одиночками.
Объекты контекста делают ваше «глобальное состояние» явным, и поэтому его легче рассуждать. Если функция не принимает объект контекста, вы знаете, что она не использует никакого глобального состояния контекста. У вас нет такой гарантии с одиночными или глобальными переменными.
Контекстные объекты будут немного медленнее, если вы их не используете, потому что вы добавляете другой параметр ко всем вызовам функций. Они могут быть быстрее глобальных, если вы их используете, и почти всегда быстрее, чем синглтоны.
Контекстные объекты легче реализовать; обычно они живут в куче или складываются обычным образом. У синглетонов есть сложные проблемы, связанные с многопоточностью на многих языках.
Так что нет, это не синглтон, это лучше, чем синглтон.
Тем не менее, вы по-прежнему обмениваетесь дурацким состоянием - тот факт, что вы храните все это в одной локальной переменной, делает ее более явной, но все же создает серьезную путаницу проблем . Имейте в виду одно правило ответственности . Имеет смысл иметь контекст, который владеет плеером и текущим уровнем - они связаны - но почему тот же контекст владеет вашим вводом с клавиатуры?
Рассмотрим разные уровни контекстов, например:
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и беги с этим.
Большинство решений этой проблемы, включая паттерн Синглтона, включают использование статических переменных. Если у вас когда-либо будет только один игрок, вы можете просто указать Player как одноэлементный класс, что означает, что вы можете получить доступ к экземпляру Player через что-то вроде Player.currentPlayer. Однако многие люди злятся на синглетонов. Вы также можете иметь ResourceManager или аналогичный класс, который содержит статические ссылки на различные полезные глобальные переменные или довольно-таки чертовски глобальные переменные. В вашем коде вы также можете сделать статически доступными переменные «Gateway» вместо того, чтобы раздувать ваш код, передавая его повсюду.
Вопрос существенно изменился с тех пор, как я сделал этот ответ, настолько, что его редактировать не стоит.
Грегори Эйвери-Вейр
2
Кроме названия ничего не изменилось в вопросе.
bummzack
1
Какая? Ничего не изменилось, кроме названия. -1
AttackingHobo
Я думаю, что я думал о названии здесь; Я помню, что оригинальное название было что-то вроде "Как мне это сделать?" Вполне возможно, что я неправильно прочитал первоначальный заголовок / вопрос, когда сделал ответ.
Это не похоже на паттерн Синглтона. Насколько я понимаю, вы передаете объект со ссылками на важные игровые объекты всем своим экземплярам.
Если бы это был шаблон Singleton, вы бы имели:
Тогда как в вашем случае вы могли бы иметь:
Это выглядит в основном так же, но на самом деле это не так. Если вы хотите заменить
AudioManager
на новый (расширенный класс), какExtendedAudioManager
, вы бы попали в стену, используя шаблон Singleton. Ваш подход к шлюзу справится с этим просто отлично.Недостаток вашего подхода в том, что вам придется обойтись
gateway
повсюду. Шаблон локатора службы (предложенный Джо Wreschnig в этой теме), выглядит как замена хорошей для вашего «шаблона шлюза».Иногда лучше просто работать с простым и понятным методом, а не с чрезмерным дизайном. Особенно, когда это маленький проект или прототип. Может быть, вы могли бы сделать это
gateway
своего рода глобальной переменной .. например.Game.gateway
и беги с этим.источник
Большинство решений этой проблемы, включая паттерн Синглтона, включают использование статических переменных. Если у вас когда-либо будет только один игрок, вы можете просто указать Player как одноэлементный класс, что означает, что вы можете получить доступ к экземпляру Player через что-то вроде Player.currentPlayer. Однако многие люди злятся на синглетонов. Вы также можете иметь ResourceManager или аналогичный класс, который содержит статические ссылки на различные полезные глобальные переменные или довольно-таки чертовски глобальные переменные. В вашем коде вы также можете сделать статически доступными переменные «Gateway» вместо того, чтобы раздувать ваш код, передавая его повсюду.
источник