Я просто пытался объяснить шаблон Observer коллеге для использования в приложении С#. Я заметил, что это должно быть достаточно легко реализовать, просмотрев документацию MSDN. Однако я с удивлением обнаружил, что пример MSDN отличается от того, как меня научили шаблону Observer. Имейте в виду, я в основном использовал шаблон в Java, но у меня создалось впечатление, что реализация.Net была почти такой же.
Модель, которую я знаю, использует методы Notify, Subscribe и Unsubscribe. Эта новая реализация, описанная в MSDN, использует OnNext, OnCompleted, OnError и Subscribe. Тем не менее, я могу найти статьи всего несколько лет назад, объясняя версию Notify.
На первый взгляд эта новая версия кажется излишне запутанной, и она меня слегка смущает. С каких это пор эта реализация была реализована и почему она была реализована таким образом? Ват - это преимущества?
Имейте в виду, что интерфейсы.NET Observer тесно связаны с MS Reactive Extensions. Если вы хотите понять добавленную функциональность, предоставляемую OnError/OnCompleted, это, вероятно, лучшее место для исследований. Остальная часть шаблона в основном совпадает с:
Так что единственной новой функциональностью является OnError (предоставление параллельного канала сообщения об ошибках, позволяющего наблюдателю знать, что наблюдаемое ввело состояние ошибки) и OnCompleted (чтобы наблюдатель знал, что наблюдаемый не будет предоставлять больше сообщений. ) Вы можете выполнить это с подробностями в сообщении, чтобы указать эти переходы состояния, но наличие их испеченных имеет смысл, если вы думаете о наблюдаемом как своего рода канал сообщений, который может претерпеть изменения состояния, которые несколько ортогональны намерению сами сообщения.
Четыре интерфейса, на которые нужно обратить внимание, заключаются в следующем.
IEnumerable<T>
IEnumerator<T> GetEnumerator()
IEnumerator<T>
bool MoveNext()
T Current { get; }
void Dispose()
IObservable<T>
IDisposable Subscribe(IObserver<T>)
IObserver<T>
void OnNext(T)
void OnError(Exception)
void OnCompleted()
Интерфейсы IEnumerable<T>
и IObservable<T>
являются двойственными. То же самое касается IEnumerator<T>
и IObserver<T>
. Интерактивные интерфейсы, IEnumerable<T>
и IEnumerator<T>
, используют семантику pull для описания последовательности T
s. Реактивные интерфейсы, IObservable<T>
и IObserver<T>
, используют push-семантику для описания последовательности T
s.
Предположим, что у меня есть IEnumerator<T>
именем e
. Когда я вызываю e.MoveNext()
а затем e.Current
в случае успеха, я концептуально получаю одну из трех вещей:
e.MoveNext()
возвращает true
и я получаю T
e.MoveNext()
выбрасывает Exception
e.MoveNext()
возвращает false
и у меня есть завершение Обратите внимание, как они точно соответствуют IObserver<T>
OnNext
, OnError
, OnCompleted
. Разница заключается в том, что в случае IEnumerator<T>
я IObserver<T>
информацию, но в случае IObserver<T>
я нажимаю информацию.
Когда я вызываю IEnumerator<T>.Dispose
, последовательность T
отменяется. Аналогично, когда я вызываю Dispose
в IDisposable
возвращаемом IObservable<T>.Subscribe
, последовательность T
отменяется.
Когда я вызываю IEnumerable<T>.GetEnumerator
я вытаскиваю IEnumerator<T>
. Когда я вызываю IObservable<T>.Subscribe
я нажимаю IObserver<T>
.