Должен ли я создавать интерфейсы для получателей сообщений? - PullRequest
1 голос
/ 06 марта 2012

В игровом движке, с которым я работаю (Unity), базовый класс для каждого игрового объекта имеет метод 'SendMessage ("methodName")', который вызывает указанный метод в каждом классе каждого объекта, который с ним связан - если у него есть один.

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

Ответы [ 3 ]

2 голосов
/ 06 марта 2012

Строгий ответ: ДА, используйте интерфейсы!Реальный ответ: это может зависеть.В общем, использование строк таким способом опасно (что если объявление метода изменится? Что если вы введете имя метода неправильно? У вас есть какие-либо проблемы с безопасностью?).Ответ на эти вопросы всегда таков: вы поймете эти проблемы во время выполнения, а не во время компиляции (и это означает, что вы можете выпустить что-то, что не работает, даже если это какая-то ошибка, которую ДОЛЖНО БЫТЬ найдено при компиляции).время).Более того, не забывайте исполнения, используя строки, вы должны использовать Reflection (я думаю / надеюсь, у вас не будет большого оператора switch / case).Написание интерфейсов утомительно, но 99% раз - лучший способ сохранить ваш код чистым и простым в обслуживании.Тем не менее, вы МОЖЕТЕ использовать эти строки для вызова методов (я имею в виду, например, об агентах Java или какой-то «динамической» реализации на основе конфигурации или содержимого сообщений).Так что я думаю, правильный ответ - ЭТО ЗАВИСИТ.Я думаю, что вы всегда должны использовать интерфейсы из-за скорости, проверки ошибок, обслуживания и безопасности (где это применимо).ИНОГДА вам может понадобиться использовать текстовые сообщения, но вы должны использовать их осторожно и никогда, потому что вы будете писать меньше кода (это НИКОГДА не веская причина выбирать один подход вместо другого).

Добавление: с интерфейсами, которые выможет использовать механизм «Демон сервисов» (основанный, например, на IServiceProvider), чтобы обнаружить все объекты, которые реализуют определенный интерфейс.Достичь того же самого, используя SendMessage (), может быть сложно (вы будете использовать метод CanHandlMessage ()?) И ​​подвержено ошибкам из-за дублирования.

Пример: Это всего лишь пример (чтобы объяснить, что я имею в виду с«Демон обслуживания», см. функцию FindServices (), которая извлекает все объекты, реализующие данный интерфейс), я думаю, вы бы не использовали LINQ и перечислимые элементы в вашей высокоскоростной игре.Я думаю, что это гораздо проще понять, чем SendMessage () с параметрами, и более того, обновить .

interface IEnemy
{
 Point3D Position
 {
  get;
  set;
 }

 void Destroy();
}

void FireBomb(Bomb bomb, Point3D impactLocation)
{
 IEnumerable<IEnemy> affectedEnemies = 
  FindServices<IEnemy>.Where(x.Location - impactLocation <= bomb.BlastedArea);

 Execute(affectedEnemies, x => x.Destroy());
}
2 голосов
/ 06 марта 2012

Должен ли я использовать интерфейсы, а не метод, который принимает строку и вызывает функцию?

Плюсы:

  • Безопасность времени компиляции.(Yay!).
  • Быстрее, чем отражение (профиль, чтобы увидеть, если это законный выигрыш).

Минусы:

  • Еще код для записи.

Не стесняйтесь редактировать больше плюсов / минусов.

Я бы определенно пошел по пути поиска компонентов с требуемым интерфейсом (GetComponent<IInterface> или GetComponent(typeof(IInterface)) as IInterface) и вызов метода таким образом (т.е. интерфейсы).

1 голос
/ 06 марта 2012

Если вы определяете интерфейс IGolerkaEventHandler<T> {bool InvokeHandler(T param);}, то у вас может быть метод HandleGolerkaEvent<TT>(TT param), который просматривает список WeakReference, пытается преобразовать цель каждого в IGolerkaEventHandler<TT> и вызывает InvokeHandler(param) для каждогоМетод, где работает актерский состав.Это позволило бы (требовало), чтобы разные типы «событий» принимали разные типы параметров.Может быть, а может и не быть выгодно определять T как параметр in в интерфейсе, в зависимости от того, хотите ли вы иметь ряд событий, которые для некоторых объектов могут обрабатываться общим кодом, но для других объектов могут потребоваться другиеобработки.

...