java源码阅读Observable(观察者模式)

1类签名和简介

package java.util;
public class Observable

Observable是Java内置的观察者模式中的主题类(没错,是类不是接口),和其对应的观察者接口是Observer,观察者模式是JDK中使用最多的模式之一。

观察者模式定义了对象之间的一对多的关系,这样一来,当一个对象(主题)改变状态时,它的所有依赖者(观察者)都会收到通知并自动更新。

Observable内部使用Vector来存储注册的观察者实例,是线程安全的。

注意:jdk将Observable实现为类而不是接口,那么就限制了其使用和复用性,因为Java是单继承的。

2成员属性

private boolean changed = false;
private Vector<Observer> obs;

当changed属性为true时才更行观察者们,该类实现了其set和清除change状态的方法。

obs存储观察者。

protected synchronized void setChanged() {
        changed = true;
    }

protected synchronized void clearChanged() {
        changed = false;
    }

public synchronized boolean hasChanged() {
        return changed;
    }

3成员方法

(1)注册

public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

将观察者注册到主题。

(2)注销

 public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

将观察者从主题中注销

(3)通知

public void notifyObservers() {
        notifyObservers(null);
    }

public void notifyObservers(Object arg) {
        //临时数组,存储vector中所有的观察者
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        //遍历所有观察者并调用其update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

4使用Observable实现观察者模式

场景:气象站每次更新气温,都到通知给3个不同的app厂商。

气象站表示主题,用WeatherData类表示。

3个App厂商表示观察者,用App1、App2、App3类表示。

import java.util.Observable;

public class WeatherData extends Observable {

    private float temperature;
    
    public void tempChanged(){
        setChanged();
        notifyObservers();
    }

    public float getTemperature() {
        return temperature;
    }

    public void setTemperature(float temperature) {
        this.temperature = temperature;
        tempChanged();
    }
    
    
}

主题每次set温度的时候,都会通知所有的观察者,会调用观察者的update进行更新。观察者App1的代码如下(App2和App3一样)

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

public class App1 implements Observer {
    
    Observable observable;
    private float temperature;
    
    public App1(Observable observable){
        this.observable = observable;
        this.observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        // TODO Auto-generated method stub

        if(o instanceof WeatherData){
            WeatherData wd = (WeatherData)o;
            this.temperature = wd.getTemperature();
            display();
        }
    }
    
    public void display(){
        System.out.println("当前温度:"+this.temperature+"摄氏度");
    }

}

实例化App1的时候会注册到主题,下面是场景测试。

public class Test {

    public static void main(String[] args) {

        //实例化主题
        WeatherData wd = new WeatherData();
        //实例化观察者,并传入主题
        App1 app1 = new App1(wd);
        //每次改变温度时,都会通知观察者更新输出。
        wd.setTemperature(20);
        wd.setTemperature(22);
        
    }     
}

运行结果如下:

当前温度:20.0摄氏度
当前温度:22.0摄氏度

完!

猜你喜欢

转载自www.cnblogs.com/ouym/p/9205743.html