Observer jest przestarzały w Javie 9. Czego powinniśmy używać zamiast niego?


Odpowiedzi:


104

Dlaczego? Czy to oznacza, że ​​nie powinniśmy już wdrażać wzorca obserwatora?

Odpowiadając najpierw na drugą część -

TAK , to znaczy, że nie powinieneś już wdrażaćObserveriObervablejuż.

Dlaczego zostały wycofane -

Nie zapewniły wystarczająco bogatego modelu zdarzeń dla aplikacji. Na przykład mogli popierać jedynie pogląd, że coś się zmieniło, ale nie przekazywali żadnych informacji o tym, co się zmieniło.

Odpowiedź Alexa ładnie ujmuje to z góry, że Observerma słabość: wszystkie Observablesą takie same . Musisz zaimplementować logikę opartą na instanceofi rzutować obiekt na konkretny typ do Observable.update()metody.

Aby dodać do tego błędy, takie jak nie można serializowaćObservable klasy, ponieważ nie zaimplementowała Serializableinterfejsu, a wszyscy jej członkowie byli prywatni.

Jaka jest lepsza alternatywa dla tego?

Z drugiej strony Listenersmają wiele typów i mają metody wywołania zwrotnego i nie wymagają rzutowania. Jak zauważył @Ravi w swojej odpowiedzi , możesz użyć PropertyChangeListenerzamiast tego.

Pozostała część @Deprecationzostała oznaczona odpowiednią dokumentacją do eksploracji innych pakietów, do których linki znajdują się również w innych odpowiedziach.


Zwróć uwagę, że wycofanie zostało również oznaczone analizą opisaną w tej wiadomości -

W dzisiejszych czasach każdy, kto je napotyka, prawdopodobnie trafia na nie przez pomyłkę, używając RxJavalub innych frameworków reaktywnego strumienia. W takim przypadku użytkownicy zwykle będą chcieli zamiast tego używać java.util.concurrent.Flowinterfejsów API jdk9, aby wszystkie frameworki strumieni reaktywnych były kompatybilne / interoperacyjne w ramach planowanych nadchodzących wersji zgodnych z jdk9.

Edycja : Warto również wspomnieć, że wycofanie interfejsów API nie wynika głównie z powyższego powodu, ale także z braku możliwości utrzymania takiego starszego kodu, jak wspomniano w komentarzach do kilku raportów o błędach (połączonych powyżej), które zostały zgłoszone do oznaczyć poprawę w jego realizacji w taki czy inny sposób.


3
+1. Dobra odpowiedź, chociaż wciąż próbuję to zrozumieć. Czy Observer w Javie jest przestarzały z powodu jakiegoś nieodłącznego problemu samego wzorca projektowego (jak zdefiniowano w książce przez GOF) lub problemu z obsługą wzorca przez Javę? W innych językach OO, takich jak C #, C ++, Python, czy wzorzec projektowy obserwatora również ma ten sam problem, co w Javie?
Tim

25
Fakt, że dana implementacja jest przestarzała, nie oznacza, że wzorzec Observer ma fatalną wadę. Listenerjest także obserwatorem.
chrylis

@chrylis Dzięki, nie mogę się więcej zgodzić, jednym z głównych powodów wycofania API jest również związana z nim konserwacja oraz to, że zmiana jego implementacji mogła spowodować złamanie innego kodu.
Naman

@ curious95 Nie jestem w stanie zrozumieć sposobu powiadamiania w tym samym czasie .
Naman

4
@ curious95 Tak, wywołanie notifyObservers()jest równoczesne. Oto kodlet z tego samego udostępnionego, aby szczegółowo wyjaśnić jego funkcjonalność.
Naman

37

Tak, jest przestarzała w Javie 9 . I nie możemy już implementować wzorca obserwatora.


Dlaczego?

Powodów jest więcej:

Not Serializable - ponieważ Observable nie implementuje Serializable. Nie możesz więc serializować Observable ani jego podklasy.

Brak bezpieczeństwa wątków - metody mogą być przesłonięte przez ich podklasy, a powiadamianie o zdarzeniach może występować w różnej kolejności i być może w różnych wątkach, co jest wystarczające, aby zakłócić jakiekolwiek „bezpieczeństwo wątków”.

Mniej do zaoferowania -

Nie zapewniają wystarczająco bogatego modelu zdarzeń dla aplikacji. Na przykład wspierają jedynie pogląd, że coś się zmieniło, ale nie przekazują żadnych informacji o tym, co się zmieniło

Otwarte problemy - jak wspomniano, pojawiło się wiele poważnych problemów (bezpieczeństwo wątków, możliwość serializacji), a większość z nich była złożona i nadal „nie została naprawiona” lub „ Brak aktywnego rozwoju” , i to jest powód, dla którego został wycofany .

Poleciłbym również przeczytać tę odpowiedź. Dlaczego wzorzec obserwatora powinien być przestarzały? , @Jeff wyjaśnił inne powody wycofania.


Więc jaką mamy alternatywę?

Możesz użyć PropertyChangeEventi PropertyChangeListenerz java.beanspakietu.


PropertyChangeListenerzastępuje Observer, ale co powinienem rozszerzyć / wdrożyć zamiast Observable?
LastStar007

Aktualizacja: Myślę, że podejście polega na dodaniu PropertyChangeSupportzmiennej instancji a, ale byłbym wdzięczny za potwierdzenie.
LastStar007

3
@ LastStar007 Myślę, że masz rację. Znalazłem przykładowy kod na Baeldung.com , który właśnie to robi.
Dragos Stanciu

13

Dlaczego Observer jest przestarzały w Javie 9?

Odp:Observable klasy i Observerinterfejs są nieaktualne w Javie 9 ponieważ model event wspierany przez Observeri Observablejest dość ograniczony, kolejność zgłoszeń dostarczane przez Observableto nieokreślone, a zmiany państwowe nie są w jeden do jednego korespondencji z powiadomień.

Zobacz dokumentację Java https://docs.oracle.com/javase/9/docs/api/java/util/Observable.html

Alternatywny wzorzec obserwatora?

Istnieje wiele alternatyw wzorców projektowych Observer, a strumienie reaktywne są jedną z nich.

Strumienie reaktywne lub Flow API :

Flowjest wprowadzony w Javie klasa 9 i ma 4 powiązane ze sobą interfejsy: Processor, Publisher, Subscriberi Subscription.

Flow.Processor : Składnik, który działa zarówno jako subskrybent, jak i wydawca.

Flow.Publisher : Producent przedmiotów otrzymanych przez subskrybentów.

Flow.Subscriber : Odbiorca wiadomości.

Flow.Subscription: Kontrola wiadomości łącząca a Flow.Publisheri Flow.Subscriber.

Zobacz dokumentację Java https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html


7

Biorąc pod uwagę, że Observableklasa i Observerinterfejs są przestarzałe od wersji Java 9. Zgodnie z postem Java's Observer and Observable Are Deprecated in JDK 9

Model zdarzeń obsługiwany przez Observer i Observable jest dość ograniczony, kolejność powiadomień dostarczanych przez Observable jest nieokreślona, ​​a zmiany stanu nie są w korespondencji jeden do jednego z powiadomieniami. Aby uzyskać bogatszy model zdarzeń, rozważ użycie java.beans pakietu. Aby zapewnić niezawodną i uporządkowaną wymianę wiadomości między wątkami, rozważ użycie jednej z współbieżnych struktur danych w java.util.concurrentpakiecie. Aby zapoznać się z programowaniem w stylu strumieni reaktywnych, zobacz interfejs API Flow.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.