1类签名和简介

  1. package java.util;
  2. public class Observable

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

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

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

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

2成员属性

  1. private boolean changed = false;
  2. private Vector<Observer> obs;

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

obs存储观察者。

  1. protected synchronized void setChanged() {
  2. changed = true;
  3. }
  4.  
  5. protected synchronized void clearChanged() {
  6. changed = false;
  7. }
  8.  
  9. public synchronized boolean hasChanged() {
  10. return changed;
  11. }

3成员方法

(1)注册

  1. public synchronized void addObserver(Observer o) {
  2. if (o == null)
  3. throw new NullPointerException();
  4. if (!obs.contains(o)) {
  5. obs.addElement(o);
  6. }
  7. }

将观察者注册到主题。

(2)注销

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

将观察者从主题中注销

(3)通知

  1. public void notifyObservers() {
  2. notifyObservers(null);
  3. }
  4.  
  5. public void notifyObservers(Object arg) {
  6. //临时数组,存储vector中所有的观察者
  7. Object[] arrLocal;
  8.  
  9. synchronized (this) {
  10. if (!changed)
  11. return;
  12. arrLocal = obs.toArray();
  13. clearChanged();
  14. }
  15. //遍历所有观察者并调用其update方法
  16. for (int i = arrLocal.length-1; i>=0; i--)
  17. ((Observer)arrLocal[i]).update(this, arg);
  18. }

4使用Observable实现观察者模式

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

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

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

  1. import java.util.Observable;
  2.  
  3. public class WeatherData extends Observable {
  4.  
  5. private float temperature;
  6.  
  7. public void tempChanged(){
  8. setChanged();
  9. notifyObservers();
  10. }
  11.  
  12. public float getTemperature() {
  13. return temperature;
  14. }
  15.  
  16. public void setTemperature(float temperature) {
  17. this.temperature = temperature;
  18. tempChanged();
  19. }
  20.  
  21. }

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

  1. import java.util.Observable;
  2. import java.util.Observer;
  3.  
  4. public class App1 implements Observer {
  5.  
  6. Observable observable;
  7. private float temperature;
  8.  
  9. public App1(Observable observable){
  10. this.observable = observable;
  11. this.observable.addObserver(this);
  12. }
  13.  
  14. @Override
  15. public void update(Observable o, Object arg) {
  16. // TODO Auto-generated method stub
  17.  
  18. if(o instanceof WeatherData){
  19. WeatherData wd = (WeatherData)o;
  20. this.temperature = wd.getTemperature();
  21. display();
  22. }
  23. }
  24.  
  25. public void display(){
  26. System.out.println("当前温度:"+this.temperature+"摄氏度");
  27. }
  28.  
  29. }

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

  1. public class Test {
  2.  
  3. public static void main(String[] args) {
  4.  
  5. //实例化主题
  6. WeatherData wd = new WeatherData();
  7. //实例化观察者,并传入主题
  8. App1 app1 = new App1(wd);
  9. //每次改变温度时,都会通知观察者更新输出。
  10. wd.setTemperature(20);
  11. wd.setTemperature(22);
  12.  
  13. }
  14. }

运行结果如下:

  1. 当前温度:20.0摄氏度
  2. 当前温度:22.0摄氏度

完!

java源码阅读Observable(观察者模式)的更多相关文章

  1. Java源码阅读的真实体会(一种学习思路)

    Java源码阅读的真实体会(一种学习思路) 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈 ...

  2. Java源码阅读的真实体会(一种学习思路)【转】

    Java源码阅读的真实体会(一种学习思路)   刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+ ...

  3. 如何阅读Java源码 阅读java的真实体会

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心.   说到技术基础,我打个比 ...

  4. [收藏] Java源码阅读的真实体会

    收藏自http://www.iteye.com/topic/1113732 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我 ...

  5. java源码阅读Hashtable

    1类签名与注释 public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, C ...

  6. Java源码阅读Stack

    Stack(栈)实现了一个后进先出(LIFO)的数据结构.该类继承了Vector类,是通过调用父类Vector的方法实现基本操作的. Stack共有以下五个操作: put:将元素压入栈顶. pop:弹 ...

  7. Java源码阅读顺序

    阅读顺序参考链接:https://blog.csdn.net/qq_21033663/article/details/79571506 阅读源码:JDK 8 计划阅读的package: 1.java. ...

  8. java源码阅读LinkedBlockingQueue

    1类签名与简介 public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements Blocking ...

  9. java源码阅读ArrayBlockingQueue

    1类签名与简介 public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQ ...

随机推荐

  1. poj 3404&&poj1700(贪心)

    Bridge over a rough river Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4143   Accept ...

  2. StyleCop setting

    StyleCop下载地址:http://stylecop.codeplex.com/ -Documentation Rules 文档化注释规则 -Element Documentaion 变量的文档化 ...

  3. 17-7-25-js记录

    先说明下为什么说好每天一更,周五周六周日都没有更新.因为在周五的时候,上司主动找我谈了转正后的工资4-4.5K.本来想好是6K的,后来打听了一圈公司的小伙伴,都是5-5.5,我就把自己定到了5K.万万 ...

  4. HDU 6107 Typesetting (倍增)

    Typesetting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. angularjs学习笔记1-angular总体简介及其特点

    以前开发(web或者移动端)前端主要使用jQuery+原生js,如果使用某些前端UI框架的话,它自己还可能提供一些API可以使用.而且目前很多UI框架都是基于jQuery的,所以说一下由jQuery跨 ...

  6. Codeforces 555 C. Case of Chocolate

    \(>Codeforces \space 555 C. Case of Chocolate<\) 题目大意 : 有一块 \(n \times n\) 的倒三角的巧克力,有一个人要吃 \(q ...

  7. 【差分约束系统】【强连通分量缩点】【拓扑排序】【DAG最短路】CDOJ1638 红藕香残玉簟秋,轻解罗裳,独上兰舟。

    题意: 给定n个点(点权未知)和m条信息:u的权值>=v的权值+w 求点权的极小解和极大解(无解则输出-1) 极小解即每个点的点权可能的最小值 极大解即每个点的点权可能的最大值 题解: 差分约束 ...

  8. Problem E: 12306

    #include <stdio.h> struct student{ int n; int m;}; int main(void) { int T; int k,g,i,j; ],max; ...

  9. Problem A: 零起点学算法91——找出一个数组中出现次数最多的那个元素

    #include<stdio.h> int main() { ],b[]={}; while(scanf("%d",&n)!=EOF) { ;i<n;i+ ...

  10. bootstrap中日历组件只显示年月

    大多数情况下日历组件我们使用的都是yyyy-mm-dd的日历格式,但是有时候需求不需要我们精确到日,而是最小单位到月份(yyyy-mm),网上找了很多方法,但是都没有我想要的效果,一些属性的设置都没有 ...