• 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摄氏度

    完!

  • 相关阅读:
    Mysql常用命令行大全(转)
    python 列表返回重复数据的下标
    啊哈算法, 水管工游戏
    python 实现结构体
    最长子回文字符串(Manacher’s Algorithm)
    一张图说明容器和镜像和仓库的关系
    nginx命令大全
    Django(request和response)
    python django + js 使用ajax进行文件上传并获取上传进度案例
    详解django三种文件下载方式
  • 原文地址:https://www.cnblogs.com/ouym/p/9205743.html
Copyright © 2020-2023  润新知