Jaka jest różnica między obserwatorem a subskrybentem?

85

Próbuję rozszyfrować następującą funkcję:

Subscription getCar(id, Observer<Car> observer) {
    return getCarDetails(id, new Observer<CarDetails> {
                             @Override
                             onNext(CarDetails details) {           
                                 observer.onNext(details.getCar());
                             } });
}

Mam dobre wprowadzenie do rxjavy z http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/, ale wspomniałem tylko na marginesie o Observer, mówiąc, że będziesz używać subskrybenta przez większość czas do pozycji konsumenckich wyemitowanych z Obserwowalnego.

Czy ktoś może mi wyjaśnić

  1. Kim jest obserwator?
  2. Czym różni się obserwator od subskrybenta?
  3. Co robi powyższy fragment kodu?

Javadoc sprawiał, że wyglądał jak subskrybent. Javadoc dla subskrybenta twierdzi, że implementuje obserwatora i subskrypcję. Jestem zdezorientowany.

MarcusH
źródło
To wzorzec obserwatora a publikacja / subskrypcja . Są podobne, ale mają subtelne różnice.
Sean Patrick Floyd
4
@SeanPatrickFloyd: Czy możesz wyjaśnić różnice?
user541686
Co to jest zmienna „szczegóły”?
Marian Paździoch

Odpowiedzi:

65

EDYTOWANE : z komentarzem @ Alrid

tl; dr

public abstract class Subscriber<T> implements Observer<T>, Subscription

Czyli abonent jest implementacją obserwatora , z dodatkową semantyką przy subskrypcji (chodzi bardziej o anulowanie subskrypcji). Kod w twoim pytaniu pokazuje tylko, że przechodzi przez Observerinterfejs, a nie implementację (zwykła praktyka programowania).

Również ten kod zwraca a Subscription, może to być spowodowane tym, że autor tego kodu uważał, że klient powinien mieć dostęp tylko do Subscriptionmetod, bez dostępu do elementów wytwarzanych przez to, co obserwowalne. To może być błąd programisty.

długa historia

Naprawdę powinieneś przeczytać zawartość tej strony (lub książki): http://www.introtorx.com Chodzi o Rx.Net, ale koncepcje są takie same, zostały stworzone przez Erika Meijera, a realizatorzy RxJava podążali za nimi ( jeśli dotyczy języka Java).

Ta strona Cię zaciekawi (jest to rozdział drugi): Typy klawiszy

Tutaj przeczytasz w pierwszych akapitach:

Istnieją dwa kluczowe typy, które należy zrozumieć podczas pracy z Rx i podzbiór typów pomocniczych, które pomogą Ci efektywniej nauczyć się Rx. IObserver i IObservable tworzą podstawowe bloki konstrukcyjne dla Rx, podczas gdy implementacje ISubject skracają krzywą uczenia się deweloperów, którzy nie znają Rx.

...

Zasadniczo Rx jest zbudowany na podstawach wzorca Observer. NET udostępnia już inne sposoby implementacji wzorca obserwatora, takie jak delegaci multiemisji lub zdarzenia (które zwykle są delegatami multiemisji).

Nawet jeśli typy / API są nieco inne, wiele się nauczysz dzięki tej książce, prawdopodobnie o wiele więcej niż w przypadku niektórych blogów.

Czego ta książka nie mówi ( ... ponieważ jest w implementacji RxJava )

Główny programista RxJava w tym czasie wprowadził niewielką zmianę (patrz PR # 792 ), która pozwoliła wyróżnić dwa rodzaje umów:

  • powiadomienie -> Observer
  • (nie) subskrypcja -> Subscription

Ta zmiana pozwoliła lepiej wyrazić / podzielić te obawy dotyczące klas implementujących biblioteki RxJava.

Jednak jako użytkownik biblioteki korzystanie z rzeczywistych implementacji biblioteki RxJava powinno wystarczyć.

Wdrożenie abonenta wymaga znacznie więcej wiedzy, pracy i staranności, w istocie semantyka subskrypcji jest bardzo ważna w zależności od rodzaju obserwowalnego źródła (gorące czy zimne? Drogie w tworzeniu?)


Ujawnianie Subscriberraczej niż Observerw przypadkach takich jak powyżej nie będzie kolidować z kodem w większości przypadków, ale nie jest to jego zamierzone użycie, chyba że te semantyki bez subskrypcji są potrzebne. Ale ostatecznie wdrożenie Subscribera może wiązać się z wpadnięciem w pewne pułapki, takie jak:

  1. wydawać zasoby na funkcje, których nie będziesz używać
  2. nie może dziedziczyć z innej klasy
  3. napisz niepoprawny kod anulowania subskrypcji
  4. kopiuj / wklej kod nieprawidłowy kod lub poprawny kod napisany dla innego kontekstu
Brice
źródło
1
W 2.x Observer służy do subskrybowania Observable, a Subscriber jest używany do subskrybowania Flowable, Subscriber nie implementuje już Observera, github.com/ReactiveX/RxJava/issues/4515
sarvesh chavan
40

(Edycja: najwyraźniej dotyczy to tylko RxJava 1.)

  1. Jest Observerto obiekt, który może pobierać dane ze źródła danych (an Observable). Źródło danych wypycha dane do niego, wywołując dane obserwatora onNext().

  2. A Subscriberto, Observerktóry może również wypisać się z tego źródła danych (przez Subscriptioninterfejs).

  3. getCar()Funkcja próbuje powrócić samochody, ale nie ma bezpośredni sposób to zrobić. Istnieje jednak funkcja, która pobiera szczegóły samochodu ( getCarDetails()), która wywoła obserwatora ze wszystkimi szczegółami samochodu. Dlatego wywołuje tę funkcję i przekazuje ją jako obserwatorowi, który po otrzymaniu danych pobierze dane samochodu ze szczegółów i przekaże je własnemu obserwatorowi.

Lawrence Kesteloot
źródło
2
Nie jest to prawdą, ponieważ w RxJava 2 abonent i obserwator to dwa zupełnie różne interfejsy. Żadne nie przedłuża drugiego
FRR
19

W RxJava 2 org.reactivestreams.Subscriber jest interfejs zgodny ze specyfikacją Reactive Streams .

Główną różnicą Observablejest to, że nowe Subscriberpodpory przeciwciśnienia.

Observerjest subskrybowany Observablei Subscribersubskrybowany Flowable(implementuje org.reactivestreams.Publisher).

Zobacz szczegółowy opis tutaj .

Yaroslav Stavnichiy
źródło
3

Również w RxJava2 , jeśli chcesz mieć możliwość anulowania subskrypcji, powinieneś użyć ResourceObserverfor Observablei ResourceSubscriberfor Flowable.

Sprawdź to pytanie

Beshoy Fayez
źródło