zoukankan      html  css  js  c++  java
  • 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摄氏度

    完!

  • 相关阅读:
    我觉得总结的不错的entityFramework
    vs2013引入com组件后,发布时如何提取出dll文件
    win10创建扩展分区
    web.config配置
    mysql时间增加一年
    json介绍
    phpcms列表分页ajax加载更多
    phpcms批量更新内容页只更新一点就返回问题
    phpcms不能批量更新栏目页和内容页
    iis设置默认文档,提示web.config配置xml格式不正确
  • 原文地址:https://www.cnblogs.com/ouym/p/9205743.html
Copyright © 2011-2022 走看看