Скажем, мне нужен класс обслуживания, который публикует данные, и подписчики могут подписаться на данные интересов.
Как мне создать интерфейс? Это плохой дизайн для прохождения обратных вызовов? Мне не кажется OO
Опция 1
public int Subscribe(string code, DataUpdatedDelegate callback)
{
this.subscribers[subscriptionId] = callback;
this.codeSubscribers[code].Add(subscriptionId);
...
return subscriptionId;
}
public void UnSubscribe(int subscriptionId)
{
foreach list in codeSubscribers
remove subscriptionId
subscribers.remove(subscriptionId)
}
private void OnDataUpdated(int code, Data data)
{
List<int> interestedSubscribers = codeSubscribers[code];
foreach (int subId in interestedSubscribers)
{
DataUpdatedDelegate callback = this.subscribers[subId];
callback(data);
}
}
Вариант 2
public interface ISubscriber
{
void ProcessData(Data data);
}
public int Register(ISubscriber subscriber)
{
return subscriptionId;
}
public void Subscribe(string code, int subscriptionId)
{
}
... rest similar to option 1
Это классический случай шаблона Observer, я бы определенно пошел с вариантом 2. Использование интерфейса дает вам больше возможностей. Если позже вам нужно добавить дополнительные методы в интерфейс, вам не нужно будет менять код.
Теоретически, интерфейс не должен меняться после его выхода в дикую природу. Имейте это в виду, если вы решите использовать его.
Конечно, то же самое можно сказать о подписке делегата. Опять же, вы всегда можете обеспечить перегрузку методов и множество перегрузок делегатов (рассмотрите, например, Action <T>, Action <T1, T2> и т.д.).
Оба метода имеют свои плюсы и минусы; ни одна серебряная пуля. Один, который может привести вас к интерфейсу, - это тестируемость. Было бы намного проще высмеять обратный вызов, если бы у вас был интерфейс для использования. Опять же, это может быть так же просто с делегатом. Однако, если вы используете насмешливую фреймворк или инъекцию зависимостей, интерфейсы, скорее всего, пройдут.
Я бы пошел с делегатами, давал больше информации о полезности re message, только методы подписывались не на объекты и не возились с ext/interface/mixins/etc. Это эквивалент С# того, что используется в Python для pypubsub (http://pypubsub.sourceforge.net), который отлично работает.