我们什么时候应该使用 Observer 和 Observable?

一位面试官问我:

什么是观察者和可观察者,我们什么时候应该使用它们?

我不知道这些术语,所以当我回到家并开始谷歌搜索和时,我从不同的资源中找到了一些观点:ObserverObservable

1)Observable是一个类,Observer是一个接口。

2) 该类维护一个列表。ObservableObserver

3)当一个对象被更新时,它调用它每个s的方法来通知,它被改变了。Observableupdate()Observer

我发现了这个例子:

import java.util.Observable;
import java.util.Observer;

class MessageBoard extends Observable
{
    public void changeMessage(String message) 
    {
        setChanged();
        notifyObservers(message);
    }
}

class Student implements Observer 
{
    @Override
    public void update(Observable o, Object arg) 
    {
        System.out.println("Message board changed: " + arg);
    }
}

public class MessageBoardTest 
{
    public static void main(String[] args) 
    {
        MessageBoard board = new MessageBoard();
        Student bob = new Student();
        Student joe = new Student();
        board.addObserver(bob);
        board.addObserver(joe);
        board.changeMessage("More Homework!");
    }
}

但我不明白为什么我们需要和?和 方法有哪些用途?ObserverObservablesetChanged()notifyObservers(message)


答案 1

您有一个学生和留言板的具体示例。学生通过将自身添加到希望在将新消息发布到消息板时收到通知的观察者列表中进行注册。将消息添加到消息板时,它将循环访问其观察者列表,并通知他们发生了事件。

想想推特。当你说你想关注某人时,Twitter会将你添加到他们的关注者列表中。当他们发送新推文时,您会在输入中看到它。在这种情况下,你的Twitter帐户是观察者,你关注的人是观察者。

这个类比可能并不完美,因为Twitter更有可能成为调解人。但它说明了这一点。


答案 2

用非常简单的术语(因为其他答案无论如何都会向您推荐所有官方设计模式,因此请查看它们以获取更多详细信息):

如果你想有一个由你程序生态系统中的其他类监视的类,你说你希望这个类是可观察的。即,其状态可能会有一些变化,您希望将其广播到节目的其余部分。

现在,要做到这一点,我们必须调用某种方法。我们不希望 Observable 类与有兴趣观察它的类紧密耦合。它不在乎它是谁,只要它符合某些标准。(想象一下,这是一个广播电台,只要他们有一个FM收音机调谐到他们的频率,它就不在乎谁在听)。为了实现这一点,我们使用一个接口,称为观察者。

因此,Observable 类将具有一个观察者列表(即实现您可能拥有的观察者接口方法的实例)。每当它想要广播某些内容时,它只需一个接一个地在所有观察者上调用该方法。

最后要结束这个谜题的是,Observable类如何知道谁感兴趣?因此,Observable 类必须提供一些机制来允许 Observer 注册他们的兴趣。诸如此类的方法将观察者添加到观察者列表中,以便在发生重要事件时,它会遍历列表并调用列表中每个实例的 Observer 接口的相应通知方法。addObserver(Observer o)

可能是在面试中,他们没有明确地问你关于和,而是关于通用概念。这个概念是一种设计模式,Java恰好直接提供开箱即用的支持,以帮助您在需要时快速实现它。因此,我建议您了解概念而不是实际的方法/类(当您需要它们时可以查找它们)。java.util.Observerjava.util.Observable

更新

为了响应您的注释,实际的 java.util.Observable 类提供了以下功能:

  1. 维护实例列表。有兴趣收到通知的新实例可以通过 添加,也可以通过 删除。java.util.ObserveraddObserver(Observer o)deleteObserver(Observer o)

  2. 维护内部状态,指定自上次向观察者发出通知以来对象是否已更改。这很有用,因为它将您说已更改的部分与通知更改的部分分开。(例如,如果您有多个更改发生,并且您只想在过程结束时通知而不是在每个小步骤中通知,则它很有用)。这是通过 完成的。所以你只是在你把某件事改成的时候就叫它,你希望其余的人最终知道它。ObservablesetChanged()ObservableObservers

  3. 通知所有观察者特定项已更改状态。这是通过 完成的。这将在继续处理通知之前检查对象是否实际已更改(即已进行调用)。有2个版本,一个没有参数,一个有参数,以防你想通过通知传递一些额外的信息。在内部发生的事情是,它只是循环访问实例列表,并为每个实例调用update(Observable o,Object arg)方法。这告诉哪个是可观察对象发生了变化(您可能正在观察多个对象),以及可能携带一些额外信息的额外对象(通过。ObservablenotifyObservers()setChanged()ObjectObserverObserverObject argnotifyObservers()


推荐