2019独角兽企业重金招聘Python工程师标准>>>

本文主要讲解OpenJDK观察者模式的2个工具类,java.util.Observer观察者接口,java.util.Observable被观察者基类。

然后,给出了一个常见的观察者应用示例。

Observer观察者接口

/*** 一个类可以实现Observer接口,当它想要得到“被观察者”对象变化通知的时候*/
public interface Observer {/*** 当被观察的对象发生变化时,这个方法被调用。一个应用调用Observable对象的notifyObservers方法,去通知所有的观察者,   Observable对象发生了变化。* @param   o     被观察的对象.* @param   arg   传递给notifyObservers方法的参数.*/void update(Observable o, Object arg);
}

Observable被观察者基类

这个类代表一个可以观察的对象,或数据(在模型-视图范式中)。
它能够被继承去代表一个应用想要观察的对象。

一个observable对象可以有一个或多个观察者。
一个观察者可以是一个实现了Observer接口的对象。

当一个observable实例发生了变化,一个应用可以调用Observable的notifyObservers方法,去通知
它的观察者所发生的变化,通过调用观察者的update方法。

通知被传递的顺序是没有指定的。
在Observable类中的默认实现是,按注册顺序通知Observers。
但是子类可以改变这种顺序,使用没有保证的顺序,在分开的线程中传递通知,或者确保他们的子类遵循他们所选择的这个顺序。

注意:这个通知机制和线程没有任何关系,与Object对象的wait和notify机制没有任何关系。

当一个observable被新创建的时候,它的observer集合是空的。
两个observer被认为是同一个,当且仅当他们的equals方法比较返回true的时候。

public class Observable {//该对象是否已经发生了变化,默认为falseprivate boolean changed = false;//Vector是线程安全的,ArrayList是非线程安全的private Vector obs;//构造一个没有观察者的Observable对象public Observable() {obs = new Vector();}//增加一个观察者public synchronized void addObserver(Observer o) {if (o == null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}//删除一个观察者对象public synchronized void deleteObserver(Observer o) {obs.removeElement(o);} public void notifyObservers() {notifyObservers(null);}public void notifyObservers(Object arg) {//一个临时的数组缓冲,用来作为当前观察者状态的快照Object[] arrLocal;synchronized (this) {//我们不想要Observer 回调任何代码,在保持它的Monitor的时候。//从Vector中提取Observable 和存储Observer的状态的代码需要同步,但是通知观察者却不需要。//最坏的潜在竞争性条件结果是://1.一个新增加的观察者将会错误正在进行的通知//2.一个最近被取消注册的观察者将会被错误的通知,当它不需要关心的时候if (!changed)return;arrLocal = obs.toArray();clearChanged();}//通知观察者的代码,在同步块之外for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}//删除所有的观察者public synchronized void deleteObservers() {obs.removeAllElements();}//表明Observable对象已经发生了变化protected synchronized void setChanged() {changed = true;}//表明这个对象已经不再变化,或者说明已经通知到所有的观察者最近的一次变化。protected synchronized void clearChanged() {changed = false;}//测试该对象是否已经发生了变化。当且仅当setChanged方法比clearChanged方法调用的次数更多的时候,返回true。public synchronized boolean hasChanged() {return changed;}// 返回Observable对象的观察者的数量.public synchronized int countObservers() {return obs.size();}}

代码示例

书,被观察者(或者称之为订阅主题)

import java.util.Observable;//书,被观察者(或者称之为订阅主题)
public class Book extends Observable {// 书的IDprivate Integer id;// 书名private String name;// 当前价格private Double price;// 当书的价格修改时,调用该方法public void modifyPrice(Double newPrice) {ChangeStatus status = null;// 差值大于0.01,就认为价格放生了变化if (Math.abs(newPrice - price) >= 0.01) {setChanged();status = new ChangeStatus();status.setId(id);status.setName(name);status.setOldPrice(price);status.setNewPrice(newPrice);}// 通知客户书已经降价notifyObservers(status);}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}}

观察者:用户的邮箱

import java.util.Observable;
import java.util.Observer;/*** 观察者:用户的邮箱*/
public class BuyerEmail implements Observer {// 该方法会被“被观察者的父类”即Observable调用public void update(Observable o, Object arg) {// 这里做具体的发电子邮件的程序if (arg instanceof ChangeStatus) {NotifyUtils.sendEmail((ChangeStatus) arg);}}
}

观察者:用户的手机

import java.util.Observable;
import java.util.Observer;
/*** 观察者:用户的手机*/
public class BuyerMobile implements Observer {// 该方法会被“被观察者的父类”即Observable调用public void update(Observable o, Object arg) {// 这里做具体的发电子邮件的程序if(arg instanceof ChangeStatus){NotifyUtils.sendSMS((ChangeStatus)arg);}}}

一本书的信息变化的实体类

public class ChangeStatus {//书的IDprivate Integer id;//书名private String name;//过去的价格private Double oldPrice;//最新的价格private Double newPrice;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Double getOldPrice() {return oldPrice;}public void setOldPrice(Double oldPrice) {this.oldPrice = oldPrice;}public Double getNewPrice() {return newPrice;}public void setNewPrice(Double newPrice) {this.newPrice = newPrice;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

发送通知的工具类

public class NotifyUtils {// 发送邮件通知用户public static void sendEmail(ChangeStatus status) {print(status);}// 发送短信通知用户public static void sendSMS(ChangeStatus status) {print(status);}// 一种只是用来作为“演示”的发送信息的方法private static void print(ChangeStatus status) {println("*******************************************************");String messageContent = messageContent(status);println(messageContent);println("********************************************************");}private static String messageContent(ChangeStatus status) {// 一般,降价才会通知,这里只当是降价了String str = "尊敬的用户,您好!\n";str += "您收藏的图书《" + status.getName() + "》降价了。\n";str += "过去的价格是:" + status.getOldPrice() + "\n";str += "现在的价格是:" + status.getNewPrice() + "\n";str += "您可以通过以下链接 http://blog.csdn.net/FansUnion 进行购买。";return str;}private static void println(Object content) {System.out.println(content);}
}

程序入口

public class ObserverPatternTest {/*** 观察者模式-用法示例*/public static void main(String[] args) {Book book = new Book();book.setName("中国象棋程序的设计与实现");book.setPrice(45.0);// 下面的观察者在实际应用中可以从数据库或文件中读取BuyerEmail email = new BuyerEmail();BuyerMobile mobile = new BuyerMobile();// 增加观察者,在实际应用中就是哪些人对该书作了关注book.addObserver(email);book.addObserver(mobile);book.modifyPrice(34.00);}
}

输出结果

*******************************************************
尊敬的用户,您好!
您收藏的图书《中国象棋程序的设计与实现》降价了。
过去的价格是:45.0
现在的价格是:34.0
您可以通过以下链接 http://blog.csdn.net/FansUnion 进行购买。
********************************************************
*******************************************************
尊敬的用户,您好!
您收藏的图书《中国象棋程序的设计与实现》降价了。
过去的价格是:45.0
现在的价格是:34.0
您可以通过以下链接 http://blog.csdn.net/FansUnion 进行购买。
********************************************************

参考资料:OpenJDK7源码

原文参见: http://FansUnion.cn/articles/2936

转载于:https://my.oschina.net/jiutianniao/blog/399484

OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例相关推荐

  1. java 集合反射_关于granite源码包CollectionUtil集合工具类获取集合反射类型、实例化各种集合类型HashSet/ArrayList等...

    一.前言 基于granite源码包org.granite.util.CollectionUtil集合工具类,分别获取集合反射类型java.lang.reflect.Type.实例化newCollect ...

  2. java.util.list源码_关于fest-util源码包Collections集合工具类过滤、判空、格式化及复制克隆处理...

    一.前言 关于fest-util源码包org.fest.util.Collections集合处理类,实现对数组转换List序列集合.集合duplicatesFrom克隆复制.集合判空isEmpty.并 ...

  3. Go语言使用之JSO使用、源码解析和JSON工具类

    在go语言网络编程中,经常会有这样的需求:保存结构体和读取结构体数据.如果你使用redis数据库存储数据,你怎么做?Redis仅支持五种数据类型( String(字符串) .Hash (哈希).Lis ...

  4. OpenJDK源码赏析之四(jli_util中的工具函数)

    上一篇: OpenJDK源码赏析之三:Java命令参数的读取_星空_MAX的博客-CSDN博客 不承接上一篇,这篇单独开始分析jli_util.h(java工具函数)里的一些函数 JLI_MemAll ...

  5. Celery 源码解析六:Events 的实现

    序列文章: Celery 源码解析一:Worker 启动流程概述 Celery 源码解析二:Worker 的执行引擎 Celery 源码解析三: Task 对象的实现 Celery 源码解析四: 定时 ...

  6. RxJava 源码解析之观察者模式

    了解 RxJava 的应该都知道是一个基于事务驱动的库,响应式编程的典范.提到事务驱动和响应就不得不说说,设计模式中观察者模式,已经了解的朋友,可以直接跳过观察者模式的介绍,直接到 RxJava 源码 ...

  7. 转-OpenJDK源码阅读导航跟编译

    OpenJDK源码阅读导航 OpenJDK源码阅读导航 博客分类: Virtual Machine HotSpot VM Java OpenJDK openjdk 这是链接帖.主体内容都在各链接中.  ...

  8. Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator

    2019独角兽企业重金招聘Python工程师标准>>> Spring AOP 源码解析系列,建议大家按顺序阅读,欢迎讨论 Spring源码-AOP(一)-代理模式 Spring源码- ...

  9. JAVA源码优化、分析工具

    JAVA源码优化.分析工具 一.11款用于优化.分析源代码的Java工具 1. PMD from http://pmd.sourceforge.net/ PMD能够扫描Java 源代码,查找类似以下的 ...

最新文章

  1. 用了这么多年 curl,竟然不知道还有这种用法?!
  2. Android开发:Kotlin下配置DataBinding
  3. 002_JSONObject、JSONArray和JsonConfig对象简单使用
  4. Python入门100题 | 第033题
  5. 4/7 SELECT语句:过滤(组合WHERE子句)
  6. RabbitMQ初探--用C#简单实现通信服务
  7. 欢乐纪中某B组赛【2019.1.25】
  8. vba java 网页_通过VBA提交JSP网站的Java脚本表单
  9. Moreau Decomposition 和 共轭次梯度定理
  10. Eclipse关闭无用validation
  11. Java新职篇:变量的作用域和生存期
  12. 微信扫一扫打印照片的原理以及实现过程(持续更新中)
  13. 华为od业务主管面试问题-我的回答
  14. 从一个简单的数学题来说说偷换概念引发的催眠效应
  15. 动态设置高德地图中心点(坐标点),始终位于屏幕中心
  16. 个人关于工作上的一点建议
  17. Oracle日志挖掘之LogMiner
  18. 使用CSS绘制几何图形(圆形、三角形、扇形、菱形等
  19. 中国软件外包企业的出路
  20. 堪称神级的开源笔记应用!

热门文章

  1. Python的BoundedSemaphore对象和Pool对象实例
  2. 利用Java制作背单词小应用
  3. 20200910:力扣204周周赛题解上(Java/Python/Cpp)
  4. 20190808:买卖股票的最佳时机
  5. mybatis float 小数0 不显示_卧槽!用 float 存储金额,老板说损失从工资里扣!
  6. python多线程下载多个文件_python多线程下载文件 练习1
  7. django使用mysql 好处_Django使用MySQL
  8. 【VB】StrConv函数.
  9. 心情随笔(五):九月依然精彩
  10. 这个机器人花盆,给你的植物长了脚脚