JDK自带的Observable和Observer实现观察者模式

Posted 春雨如约而来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK自带的Observable和Observer实现观察者模式相关的知识,希望对你有一定的参考价值。

观察者模式是Java非常重要的一个设计模式。对于观察者模式,JDK已经为我们提供了对应的接口和类。

分别是观察者Observer,观察者也成为订阅者Subscribe,

JDK代码为:

package java.util;

/**
 * A class can implement the <code>Observer</code> interface when it
 * wants to be informed of changes in observable objects.
 *
 * @author  Chris Warth
 * @see     java.util.Observable
 * @since   JDK1.0
 */
public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object‘s
     * <code>notifyObservers</code> method to have all the object‘s
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}
Observer是一个接口,只是一个方法update用于接收通知者的通知并做出相应,具体的逻辑肯定是需要开发者自己实现的了。

被观察者(或通知者(Publish,发布者)),JDK的源码如下:

package java.util;

public class Observable {
    private boolean changed = false;
private Vector obs; /** Construct an Observable with zero Observers. */ public Observable() { obs = new Vector(); } /** * 添加一个观察者(订阅者),已经存在则不再重复添加 * 支持多线程*/ public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } /** * 删除一个观察者(订阅者Subscribe) * 支持多线程*/ public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } /** * 通知观察者(订阅者Subscribe)*/ public void notifyObservers() { notifyObservers(null); } /** * 通知观察者(订阅者Subscribe),带参数*/ public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } /** * 删除所有观察者(订阅者Subscribe) */ public synchronized void deleteObservers() { obs.removeAllElements(); } /** * 设置变更 */ protected synchronized void setChanged() { changed = true; } /** * 清除变更*/ protected synchronized void clearChanged() { changed = false; } /** * 获取变更标识
*/ public synchronized boolean hasChanged() { return changed; } /** * 获得观察者数(订阅者数Subscribe)*/ public synchronized int countObservers() { return obs.size(); } }

Java源码考虑比较周到的。首先,使用Vector,Vector相比于ArrayList来说,它是线程安全的。其次,在添加和删除观察者时对两个方法使用了synchronized关键字,

这都是在为多线程考虑。确实Java源码并不是那么可怕,它同样也是由一些最简单最基础的组合而来。

 

下面看两个实例

实例一
NumObserable是一个被观察者,当它的成员变量data的数值发生变化时,会通知所有的观察者。
NumObserable.java
/**
 * 被观察者*/
public class NumObservable extends Observable {
    
    private int data = 0;
 
    public int getData() {
       return data;
    }
 
    public void setData(int i) {
       data = i;
       setChanged();
       notifyObservers();
    }
}

NumObserver是观察者。当它的被观察者(NumObserable)执行了notifyObservers()后,它会执行uodate()方法。

NumObserver.java

public class NumObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {

        NumsObservable myObserable = (NumsObservable) o;
        System.out.println("Data has changed to " + myObserable.getData());

    }

}

测试类SingleTest,在这里将观察者加入到被观察者的观察列表中。

SingleTest.java

public class SingleTest {

    /**
     * @param args
     */
    public static void main(String[] args) {

        NumObservable number = new NumObservable();
        number.addObserver(new NumObserver());
        number.setData(1);
        number.setData(2);
        number.setData(3);

    }

}
结果:
Data has changed to 1

 Data has changed to 2

 Data has changed to 3

实例二

这个实例中,还是对data进行观察,拥有两个观察者,分别观察奇数和偶数的变化,通过notifyObservers(arg)中的参数arg来识别通知信息。
被观察者NumsObservable.java
public class NumsObservable extends Observable {
    
    public final static Integer ODD = 1;
    public final static Integer EVEN = 2;
    private int data = 0;
 
    public int getData() {
       return data;
    }
 
    public void setData(int i) {
       data = i;
       Integer flag = EVEN;
       if ((data & 0x0001) == 1)
           flag = ODD;
       setChanged();
       notifyObservers(flag);
    }

}

奇数观察者OddObserver.java

 

public class OddObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        if (arg == NumsObservable.ODD) {
            NumsObservable myObserable = (NumsObservable) o;
            System.out.println("OddObserver:Data has changed to "
                    + myObserable.getData());
        }
    }

}

 

偶数观察者EvenObserver.java

 

public class EvenObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        if (arg == NumsObservable.EVEN) {
            NumsObservable myObserable = (NumsObservable) o;
            System.out.println("EvenObserver:Data has changed to "
                    + myObserable.getData());
        }

    }

}

 

测试类MultiTest.java

 

public class MultiTest {

    /**
     * @param args
     */
    public static void main(String[] args) {

        NumsObservable number = new NumsObservable();
        number.addObserver(new OddObserver());
        number.addObserver(new EvenObserver());
        number.setData(1);
        number.setData(2);
        number.setData(3);

    }

}
结果:
OddObserver:Data has changed to 1
EvenObserver:Data has changed to 2
OddObserver:Data has changed to 3

 

 


 

以上是关于JDK自带的Observable和Observer实现观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

JDK自带的观察者模式源码分析以及和自定义实现的取舍

[Java]_[初级]_[Observer和Observable失效后如何使用java.beans包下的类来实现观察者模式]

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

java自带的观察者模式

Java_观察者模式(Observable和Observer) -转

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