【问题标题】:What is the difference between an Observer and a Subscriber?观察者和订阅者有什么区别?
【发布时间】:2015-02-24 04:25:35
【问题描述】:

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

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,说您将在大部分时间使用订阅者来消费从 Observable 发出的项目。

谁能给我解释一下

  1. 什么是观察者?
  2. 观察者与订阅者有何不同?
  3. 上面的代码sn-p是做什么的?

Javadoc 让它看起来就像一个订阅者。订阅者的 javadoc 说它实现了观察者和订阅。我很困惑。

【问题讨论】:

  • 这是Observer 模式与publish / subscribe。它们相似,但有细微的差别。
  • @SeanPatrickFloyd:你能解释一下不同之处吗?
  • 什么是'details'变量?

标签: java rx-java


【解决方案1】:

已编辑:带有@Alrid 的评论

tl;dr

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 新手的学习曲线。

...

本质上,Rx 是建立在观察者模式的基础之上的。 .NET 已经公开了一些其他方式来实现观察者模式,例如多播委托或事件(通常是多播委托)。

即使类型/API 有点不同,你也会从这本书中学到很多东西,可能比一些博客学到的要多。

这本书没有说什么...因为它在 RxJava 实现中

RxJava 的主要开发者此时引入了一个细微的变化(参见 PR #792),可以区分两种类型的合约:

  • 通知 -> Observer
  • (取消)订阅 -> Subscription

此更改允许更好地表达/拆分 RxJava 库的实现类的这些关注点。

但是,作为库用户,使用 RxJava 库的实际实现应该就足够了。

实现订阅者需要更多的知识、工作和关心,实际上订阅语义非常重要,具体取决于可观察源的类型(热还是冷?创建成本高吗?)


在大多数情况下,在上述情况下公开Subscriber 而不是Observer 不会干扰代码,但这不是它的预期用途,除非需要那些取消订阅语义。但最终实现Subscriber,可能会陷入一些陷阱,例如:

  1. 将资源用于您不会使用的功能
  2. 不能从其他类继承
  3. 写不正确的退订码
  4. 复制/粘贴错误代码或为不同上下文编写的正确代码

【讨论】:

【解决方案2】:

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

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

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

  3. getCar() 函数正在尝试返回汽车,但没有直接的方法可以做到这一点。但是有一个获取汽车详细信息的功能(getCarDetails()),它将调用具有所有汽车详细信息的观察者。因此它调用该函数并传递给它一个观察者,当它获取数据时,它将从细节中获取汽车数据并将其传递给它自己的观察者。

【讨论】:

  • 这在 RxJava 2 中是不正确的,订阅者和观察者是两个完全不同的接口。两者都没有延伸另一个
【解决方案3】:

在 RxJava 2 中 org.reactivestreams.Subscriber 是符合 Reactive Streams specification 的接口。

Observable 的主要区别在于新的Subscriber 支持背压。

Observer 订阅ObservableSubscriber 订阅Flowable(实现org.reactivestreams.Publisher)。

详细说明见here

【讨论】:

    【解决方案4】:

    同样在 RxJava2 中,如果您希望能够取消订阅,您应该使用 ResourceObserver 代表 ObservableResourceSubscriber 代表 Flowable

    查看question

    【讨论】:

      猜你喜欢
      • 2021-10-30
      • 2017-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 2018-06-11
      • 2013-03-13
      • 2016-06-26
      相关资源
      最近更新 更多