События против переопределяемых методов?
может ли кто-нибудь предоставить мне общие рекомендации относительно того, когда я должен использовать переопределяемые методы, такие как "OnMyEvent", и когда я должен использовать события, такие как "MyEvent" в C#?
существуют ли общие принципы проектирования, которые могут определить, что использовать?
2 ответов
события отлично подходят для того, когда у вас есть "есть", а переопределения намного лучше для ситуаций, когда у вас есть "есть" отношения
например, если у вас есть животное базового класса, вполне вероятно, что каждое животное будет иметь свой собственный способ перемещения. однако каждое животное каким-то образом захочет переехать.
теперь подумайте о человеке класса,который может "иметь" домашнее животное. в этом случае человек может реагировать на движение животного, но на самом деле это не так управляйте движением животного.
эти две функции смутно похожи (оба предназначены для выполнения некоторой формы динамической отправки), но не сопоставимы напрямую.
события должны уведомлять другие объекты о том, что объект пришел к какому-то переход. Это языковая функция, которая воплощает шаблон проектирования наблюдателя. Это может быть полезно во многих случаях, но не всегда полезно или желательно. Это инструмент для выполнения конкретной работы.
виртуальный функции используются для создания Объектно-Ориентированный Полиморфизм. Они основной строительный блок почти каждой картины дизайна, и много объектно-ориентированный дизайн.
чтобы попытаться сравнить их, я предположу, что вы пытаетесь реализовать некоторую форму шаблона наблюдателя с любой функцией. С этим ограничением все еще нет простого правила, на которое вы можете вернуться, чтобы решить, какой вы должны использовать. Вместо этого вам придется задавать себе вопросы например:
- кто вызвал это: будет ли действие, которое запускает переход вашего состояния, происходить внутри, или оно будет вызвано извне?
Если он запускается внутренне, вы можете использовать событие или виртуальный метод. Если он запускается извне, необходимо использовать виртуальный метод.
- кого это волнует: должен ли класс, определяющий состояние, обрабатывать последствия перехода состояния, или должен ли внешний класс обрабатывать его?
Если класс, которому принадлежит состояние, должен обрабатывать переход, то это должен быть виртуальный метод. Если отдельный класс должен реагировать на переход, это должно быть событие.
- сколько обработчиков мне нужно: вам всегда нужен один обработчик для реакции на переход состояния, или вам нужно много?
Если вам нужен один, то с помощью виртуального метода или события может считаться приемлемыми. Если вам нужно много, то будет намного проще использовать событие.
- знаю ли я, какой обработчик я хочу во время компиляции: я привязываюсь к одному известному обработчику или привязываюсь к неизвестным обработчикам, возможно, изменяясь со временем?
Если вам нужны обработчики для изменения, вы должны использовать события. Если во время компиляции известен только один обработчик, можно использовать виртуальный метод.
- как должен быть связан мой код: принадлежит ли ваш код обработчика производному классу вашего исходного типа или он принадлежит где-то еще?
Если он принадлежит производному классу, вам нужен виртуальный метод. Если он принадлежит другому, то вам нужно событие.
Как вы можете видеть, ответы будут сильно зависеть от вашей конкретной проблемной области и архитектуры объектов. Хороший дизайн-это не то, что волшебно попадает к вам на колени через какой-то контрольный список. Вы должны думать об этом, много :)
Edit:
Это может не быть непосредственно применимо к событиям C#, но может быть полезно взять пример из существующей работы. Вот краткая статья, которую я только что нашел (отвечая на другой вопрос) об альтернативах дизайна в Java для eventing patterns:http://csis.pace.edu / ~bergin/patterns/event.html