Udostępnij za pośrednictwem


Wzorzec projektowy obserwatora — Najlepsze praktyki

Na platformie .NET wzorzec projektowy obserwatora jest implementowany jako zestaw interfejsów. Interfejs System.IObservable<T> reprezentuje dostawcę danych, który jest również odpowiedzialny za zapewnienie IDisposable implementacji, która umożliwia obserwatorom anulowanie subskrypcji powiadomień. Interfejs System.IObserver<T> reprezentuje obserwatora. W tym temacie opisano najlepsze rozwiązania, które deweloperzy powinni przestrzegać podczas implementowania wzorca projektowego obserwatora przy użyciu tych interfejsów.

Wątkowość

Zazwyczaj dostawca implementuje IObservable<T>.Subscribe metodę przez dodanie określonego obserwatora do listy subskrybentów reprezentowanej przez jakiś obiekt kolekcji i implementuje IDisposable.Dispose metodę przez usunięcie określonego obserwatora z listy subskrybentów. Obserwator może wywołać te metody w dowolnym momencie. Ponadto, ponieważ umowa dostawcy/obserwatora nie określa, kto jest odpowiedzialny za anulowanie subskrypcji po IObserver<T>.OnCompleted metodzie wywołania zwrotnego, dostawca i obserwator mogą próbować usunąć tego samego członka z listy. Z tego powodu metody Subscribe i Dispose powinny być bezpieczne wątkowo. Zazwyczaj wiąże się to z użyciem kolekcji współbieżnej lub blokady. Implementacje, które nie są bezpieczne wątkowo, powinny jawnie udokumentować, że nie są.

Wszelkie dodatkowe gwarancje należy określić w warstwie na podstawie kontraktu dostawcy/obserwatora. Osoby wdrażające powinny wyraźnie zwracać uwagę, gdy nakładają dodatkowe wymagania, aby uniknąć nieporozumień użytkownika dotyczących umowy obserwatora.

Obsługa wyjątków

Ze względu na luźne sprzężenie między dostawcą danych a obserwatorem wyjątki we wzorcu projektowania obserwatora mają być informacyjne. Ma to wpływ na sposób, w jaki dostawcy i obserwatorzy obsługują wyjątki we wzorcu projektowania obserwatora.

Dostawca — wywoływanie metody OnError

Metoda OnError jest przeznaczona jako komunikat informacyjny dla obserwatorów, podobnie jak IObserver<T>.OnNext metoda. Jednak metoda została zaprojektowana tak, OnNext aby zapewnić obserwatorowi bieżące lub zaktualizowane dane, natomiast OnError metoda została zaprojektowana tak, aby wskazać, że dostawca nie może dostarczyć prawidłowych danych.

Dostawca powinien postępować zgodnie z tymi najlepszymi rozwiązaniami podczas obsługi wyjątków i wywoływania OnError metody:

  • Dostawca musi obsługiwać własne wyjątki, jeśli ma określone wymagania.

  • Dostawca nie powinien oczekiwać lub wymagać, aby obserwatorzy obsługiwali wyjątki w żaden konkretny sposób.

  • Dostawca powinien wywołać metodę OnError , gdy obsługuje wyjątek, który narusza jego zdolność do dostarczania aktualizacji. Informacje na temat takich wyjątków można przekazać do obserwatora. W innych przypadkach nie ma potrzeby powiadamiania obserwatorów o wyjątku.

Po wywołaniu OnError metody lub IObserver<T>.OnCompleted przez dostawcę nie powinno być żadnych dalszych powiadomień, a dostawca może anulować subskrypcję obserwatorów. Obserwatorzy mogą jednak w dowolnym momencie anulować subskrypcję, w tym zarówno przed, jak i po otrzymaniu powiadomieniaOnError.IObserver<T>.OnCompleted Wzorzec projektowy obserwatora nie określa, czy dostawca lub obserwator jest odpowiedzialny za anulowanie subskrypcji; w związku z tym istnieje możliwość, że oba te elementy mogą próbować anulować subskrypcję. Zazwyczaj po anulowaniu subskrypcji obserwatorów są one usuwane z kolekcji subskrybentów. W aplikacji jednowątkowej implementacja IDisposable.Dispose powinna upewnić się, że odwołanie do obiektu jest prawidłowe i że obiekt jest członkiem kolekcji subskrybentów przed podjęciem próby jego usunięcia. W aplikacji wielowątkowej należy użyć obiektu kolekcji bezpiecznego wątkowo System.Collections.Concurrent.BlockingCollection<T> , takiego jak obiekt.

Obserwator — implementowanie metody OnError

Gdy obserwator otrzymuje powiadomienie o błędzie od dostawcy, obserwator powinien traktować wyjątek jako informacyjny i nie powinien być wymagany do podjęcia żadnej konkretnej akcji.

Obserwator powinien postępować zgodnie z tymi najlepszymi rozwiązaniami podczas odpowiadania na OnError wywołanie metody od dostawcy:

  • Obserwator nie powinien zgłaszać wyjątków od implementacji interfejsu, takich jak OnNext lub OnError. Jeśli jednak obserwator zgłasza wyjątki, powinien oczekiwać, że te wyjątki nie będą obsługiwane.

  • Aby zachować stos wywołań, obserwator, który chce zgłosić obiekt przekazany do jego OnError metody, powinien owinąć Exception wyjątek przed jego zgłoszeniem. W tym celu należy użyć standardowego obiektu wyjątku.

Dodatkowe najlepsze rozwiązania

Próba wyrejestrowania w metodzie IObservable<T>.Subscribe może spowodować odwołanie o wartości null. W związku z tym zalecamy unikanie tej praktyki.

Chociaż istnieje możliwość dołączenia obserwatora do wielu dostawców, zalecanym wzorcem IObserver<T> jest dołączenie wystąpienia tylko do jednego IObservable<T> wystąpienia.

Zobacz też