【问题标题】:Observable in Java在 Java 中可观察
【发布时间】:2011-11-08 10:05:32
【问题描述】:

我正在尝试理解 Observer 和 Observable。

这是一个我想弄清楚的例子:

public class IntegerDataBag extends Observable implements Iterable<Integer> {

    private ArrayList<Integer> list= new ArrayList<Integer>();

    public void add(Integer i){
        list.add(i);
        setChanged();
        notifyObservers();
    }

    public Iterator<Integer> iterator(){
        return list.iterator();
    }

    public Integer remove (int index){
        if (index< list.size()){
            Integer i = list.remove(index);
            setChanged();
            notifyObservers();
            return i;
        }
        return null;
    }

}

public class IntegerAdder implements Observer {

    private IntegerDataBag bag;

    public IntegerAdder(IntegerDataBag bag) {
        this.bag = bag;
        bag.addObserver(this);
    }

    public void update(Observable o, Object arg) {
        if (o == bag) {
            System.out.println("The contents of the IntegerDataBag have changed");
        }
    }

}
  1. bag.addObserver() 只能是因为IntegerDataBag 扩展了Observable

  2. 这个观察者被添加到哪里?正在创建什么以及在哪里创建?

  3. setChanged()notifyObservers()有什么区别?

  4. 看不懂update方法; arg 代表什么?为什么我需要检查o==bag?为什么我要更新另一个 observable?

  5. 我为什么还需要这个观察者?

【问题讨论】:

  • 这是少数模式之一,只有在您真正需要在现有项目中使用一种模式时才能最好地理解。
  • 例如在 MVC 中。试试这个代码:emilmont.net/…

标签: java oop design-patterns observer-pattern


【解决方案1】:
  1. 是的。 addObserverObservable 抽象类中的一个方法。请参阅 Java 文档中的 Observable
  2. 它被添加到Observable 的列表中。
  3. 在设置setChanged 之前,对notifyObservers 的调用不会执行任何操作。
  4. 您可能在同一个应用程序中有多个 Observable。
  5. Observer 是一种常见的设计模式。通常的例子是当你有一个模型和多个视图时。每个视图都是模型上的观察者;如果模型发生变化,视图也会更新。

【讨论】:

  • 从记忆中,Observable 是一个抽象类,而不仅仅是一个接口。我认为 setChanged 也像标志一样使用。这是为了避免不必要的更新。 args 可以用作参数。查找 Listener,因为这种方法也用于 Java。
  • @James Poulson,Observable 根本不是抽象类(在 JDK 中)。
  • 你说得对,它实际上是一个普通/具体的类。正如本文所述,这与其他依赖接口/抽象类的设计模式的实现不同:javapractices.com/topic/TopicAction.do?Id=156
  • 它不是抽象的,但是你需要创建一个可继承的类来使用受保护的 setChanged 方法
【解决方案2】:

bag.addObserver() 只能是因为 IntegerDataBag 扩展 可观察?

是的。

2.这个观察者被添加到哪里?在哪里创建什么?

进入相关的 Observable 类,您的类正在扩展该类。

4.我不明白更新方法-args代表什么?

当观察对象的状态发生变化时调用它。 args 是传递给 nofityObserver 的参数。

为什么我需要检查那个 o==bag,我为什么要更新另一个 可以观察到吗?

您无需检查任何内容。

5.为什么我还需要这个观察者?

这是一个非常有用的设计模式。看看维基百科article

编辑: 我错过了重点:

setChanged() 和 notifyObservers() 有什么区别?

setChanged() 标记一个对象,表明它已更改。 notifyObservers 负责唤醒所有监听可观察对象的观察者。

【讨论】:

    【解决方案3】:

    回答你的观点。

    1. 是的,你是对的

    2. 观察者被添加到 Observable 对象中维护的列表中

    3. 您需要在通知观察者之前调用 setChanged(),否则他们不会知道对象已更改。一旦你调用了 notifyObservers(),所有的观察者都会被通知这个变化。如果您不先调用 setChanged,则不会通知您的观察者。

    4. arg 是您在调用 notifyObservers(arg) 时想要传递给 Observers 的任何内容;

    【讨论】:

      【解决方案4】:

      bag.addObserver() 只能因为 IntegerDataBag 扩展了 Observable 才可以制作?

      是的,addObserver 方法在Observable 中实现。

      这个观察者被添加到哪里?在哪里创建什么?

      观察者正在被添加到在Observable 中声明为私有的观察者列表中,因此它在您的子类中不可见。

      setChanged() 和 notifyObservers() 有什么区别?

      如果您在没有先拨打 setChanged() 的情况下拨打 notifyObservers(),则不会收到任何通知。

      我不明白更新方法 - args 代表什么?为什么我需要检查那个 o==bag,我为什么要更新另一个 observable?

      一个Observer可以观看多个Observables。通过检查update 方法的第一个参数,您可以确定是哪个观察者通知您某事。

      为什么我仍然需要这个观察者?

      任何时候您希望一个类向其他类发送事件,但又不希望该类直接依赖于它的观察者。

      【讨论】:

        【解决方案5】:

        观察者模式类似于监听者的概念。正在收听的对象维护其所有收听者的记录。例如,库存监视器类可能允许对象监听某个事件,例如库存水平低于警告水平。

        从观察者的角度来看:

        致电subscribe()addEventListener() 等。当事件实际发生时,观察者就会被“通知”,通常是通过调用观察者中的一个函数(事件处理函数)。

        从 observable 的角度来看:

        希望观察可观察对象的对象通过调用subscribe()addEventListener() 来注册他们的兴趣,如上所述。因此,observable 将这些观察者添加到数组、列表或其他一些数据结构中。

        一旦事件真正发生,就会通过调用观察者类中的事件处理函数来通知监听者。

        【讨论】:

          【解决方案6】:

          让我们举一个观察者模式的实际例子:Twitter。借助 Twitter,我们可以关注其他人,并近乎实时地阅读他们发布的任何内容。

          每个 Twitter 用户都是可观察的。您可以将自己添加为听众(“关注者”)并阅读他/她的帖子。每个推特用户都会做一个“通知关注者”(notifyObservers)。

          在这里我们也这样做。类IntegerDataBag 能够在其内部包中添加或删除值时通知其他类。任何实例(实现Observer)都可以将自己注册到IntegerDataBag,并通过它的回调方法(update)接收消息。

          简而言之,我们执行以下操作:

          1. 一个观察者(监听者,IntegerAdder)将自己添加到一个可观察对象IntegerDataBag
          2. observable 发生了一些事情,observable 通知它的 observers
          3. observable 会调用所有实际的observers 的回调方法
          4. 观察者现在已收到事件通知并可以使用它

          希望,这个简短的描述有助于理解这种模式。


          发布/订阅是一个类似的模式:发布者就像一个可观察者,订阅者就像一个观察者。另一个实际的例子:一个人可以订阅一份报纸,出版商会发送报纸,直到你取消订阅。

          【讨论】:

          • 那么 Observable/Observer 和 Publis/Subscriber 模式有什么区别?
          【解决方案7】:

          update() 方法由 Observable 调用。通过调用 notifyObservers() 调用此方法,该方法遍历所有 Observer 并对其调用 update。这会通知观察者他们正在观看的对象已更改并且可以执行特定操作。 args 对象是任何你想要的对象,它也可以为 null,但它可以用来通知观察者刚刚发生了什么类型的更新。

          【讨论】:

            【解决方案8】:

            bag.addObserver() 只能是因为 IntegerDataBag 扩展了 可观察到?

            正确,Observable 是具有addObserver() 方法的类。

            这个观察者被添加到哪里?正在创建什么以及在哪里创建?

            Observer 类包含Observable 对象的ListVector(在JDK 源代码中)。

            private Vector obs;
            

            这就是它的存储位置。

            setChanged()notifyObservers() 有什么区别?

            setChanged() 只是标志着Observable 已更改。 仅当 setChanged 设置为 true 时,notifyObservers() 才将列表中的所有观察者调用为 update()(将更改的对象传递给观察者)。

            我不明白更新方法 - args 代表什么?和 为什么我需要检查那个 o==bag,我为什么要更新另一个 可观察到?

            update() 方法告诉Observer 它需要根据收到的更改后的obj 进行更新。这是由Observable 中的notifyObservers() 调用的。

            我为什么还需要这个观察者?

            要为事件驱动场景创建Listener,即如果您想在可观察对象的更改中得到通知,则需要观察者。

            阅读:GoF - Observer pattern

            【讨论】:

              【解决方案9】:

              bag.addObserver() 只能因为 IntegerDataBag 扩展了 Observable 才可以制作?

              是的,这就是重点。

              这个观察者被添加到哪里?正在创建什么以及在哪里创建?

              它将IntegerAdder 添加到观察IntegerDatabag 更改的类列表中。从现在开始,如果IntegerDataBag发生变化,它会通过notifyObservers()方法通知IntegerAdder,这会触发它的update()方法。

              setChanged() 和 notifyObservers() 有什么区别?

              notifyObservers() 调用您的 observable 的每个观察者的 update() 方法,并用于将信息传递给该方法。至于setChanged(),它将您的对象标记为“已更改”,因此hasChanged() 方法现在将返回true……它用于监视对可观察类的更改。

              我不明白更新方法 - args 代表什么?

              update() 方法继承自观察者接口的实现——你必须实现它。 Object arg 是一个可选参数,您可以通过 notifyObservers() 将其传递给方法。

              为什么我需要检查那个 o==bag,我为什么要更新另一个 observable?

              由于观察者可以“观察”多个“可观察”,因此您需要检查触发update() 的确实是IntegerDatabag,因此是o==bag

              我为什么需要这个观察者?

              您需要观察者监视IntegerDataBag 的变化。在您的情况下,当 IntegerDatabag 被修改时,您会在控制台中打印一条消息。 Observer/Observable 模型的目的是专门监控特定对象的变化,然后根据变化更新程序。

              【讨论】:

                猜你喜欢
                • 2012-09-02
                • 2016-03-08
                • 1970-01-01
                • 1970-01-01
                • 2011-06-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多