观察者和订阅者有什么区别?

92

我正在尝试破译以下函数:

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

我从http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/中了解了rxjava的基础知识,但是只是简单提到了Observer,说你将大部分时间使用Subscriber来消费Observable发出的项目。

有人能向我解释一下:

  1. 什么是观察者?
  2. 观察者与订阅者有何不同?
  3. 上述代码片段是做什么的?

Javadoc让它看起来就像一个Subscriber。 Subscriber的javadoc说它实现了Observer和Subscription。 我很困惑。


这是“观察者模式”与“发布/订阅模式”的对比。它们很相似,但有微妙的差别。 - Sean Patrick Floyd
4
你能解释一下它们之间的区别吗? - user541686
“details”变量是什么? - Marian Paździoch
4个回答

75

编辑:根据 @Alrid 的评论进行了修改

总结

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

因此,SubscriberObserver的一个实现,在订阅方面具有附加语义(更多关于取消订阅)。

您问题中的代码仅显示它传递了Observer接口,而不是实现(通常的编程实践)。

此外,此代码返回一个Subscription,可能是因为此代码的作者认为客户端只能访问Subscription方法,而无法访问可观察到的元素。这可能是程序员的错误。

长话短说

我建议你阅读这个网站(或书籍)的内容: http://www.introtorx.com。它讲解Rx.Net,但是概念是相同的,由Erik Meijer创造,RxJava实现者们遵循了them(如果适用于Java语言)。

这个页面会引起你的兴趣(这是第二章): KeyTypes

在第一段中,你将会读到:

当使用Rx时,有两种关键类型需要理解,并且还有一些辅助类型可以帮助您更有效地学习Rx。IObserver和IObservable构成了Rx的基本构建模块,而ISubject的实现则可以降低新手开发人员的学习曲线。

...

基本上,Rx建立在观察者模式的基础之上。.NET已经公开了一些其他实现观察者模式的方法,例如多路广播委托或事件(通常是多路广播委托)。
即使类型/API有点不同,您也将从这本书中学到很多,可能比一些博客更多。
这本书没有提到的事情(...因为它在RxJava实现中)
此时的RxJava主要开发人员引入了一个轻微的变化(请参见PR #792),允许区分两种类型的合同:
- 通知 -> Observer - (取消)订阅 -> Subscription
这个改变允许更好地表达/拆分RxJava库的实现类的这些问题。
但是作为库用户,使用RxJava库的实际实现应该足够好。

实现订阅者需要更多的知识、工作和关注,事实上,订阅语义对源可观测对象的类型(热或冷?创建成本高?)非常重要。


在上述情况下,使用 Subscriber 而不是 Observer 通常不会干扰代码,但这并不是其预期的用途,除非需要取消订阅语义。但最终实现一个 Subscriber 可能会遇到一些问题,例如:

  1. 为你不会使用的功能花费资源
  2. 无法从另一个类继承
  3. 编写错误的取消订阅代码
  4. 复制/粘贴错误的代码或针对不同上下文编写的正确代码

3
在2.x版本中,使用Observer来订阅Observable,使用Subscriber来订阅Flowable。现在,Subscriber不再实现Observer接口。https://github.com/ReactiveX/RxJava/issues/4515 - sarvesh chavan

43

(编辑:这只适用于RxJava 1。)

  1. Observer是一个可以从数据源(一个Observable)获取数据的对象。数据源通过调用观察者的onNext()将数据推送给它。

  2. Subscriber是一个Observer,它也可以通过Subscription接口取消订阅数据源。

  3. getCar()函数试图返回汽车,但没有直接的方法来实现。但是有一个可以获取汽车详细信息(getCarDetails())的函数,它会调用一个观察者并传递所有的汽车详细信息。因此,它调用该函数并传递一个当它获得数据时将从详细信息中获取汽车数据并将其传递给自己的观察者的观察者。


2
这在 RxJava 2 中不是真的,Subscriber 和 Observer 是两个完全不同的接口,它们之间没有继承关系。 - frankelot

25
在RxJava 2中,org.reactivestreams.Subscriber 是符合Reactive Streams规范的接口。
Observable的主要区别在于新的Subscriber支持背压(backpressure)。 Observer订阅Observable,而Subscriber订阅Flowable(实现了org.reactivestreams.Publisher)。
详细描述请参见这里

3
在 RxJava2 中,如果你想要取消订阅,你应该使用 ResourceObserver 来观察 Observable 和使用 ResourceSubscriber 来观察 Flowable。具体详情可参见此问题

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接