java观察者模式介绍

概念

Observer模式定义对象间的一对多的依赖关系,当一个对象(被观察者)的状态发生改变时, 所有依赖于它的对象(观察者)都得到通知并被自动更新。JDK里提供的observer设计模式的实现由java.util.Observable类和 java.util.Observer接口组成。从名字上可以清楚的看出两者在Observer 设计模式中分别扮演的角色:Observer是观察者角色,Observable是被观察目标(subject)角色。

相关类介绍

1.Obervable类

此类表示模型视图范例中的 observable 对象,继承它的类表示应用程序想要观察的对象。一个 observable 对象可以有一个或多个观察者。观察者是实现Observer接口的任意对象。一个 observable 实例改变后,调用 Observable 的 notifyObservers 方法的应用程序会通过调用观察者的 update 方法来通知观察者该实例发生了改变。

方法摘要

void

addObserver(Observer o)

如果观察者与集合中已有的观察者不同,则向对象的观察者集中添加此观察者。未指定向多个观察者发送通知的顺序。

protected  void

clearChanged()

指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以 hasChanged 方法将返回 false。notifyObservers 方法自动调用此方法。

int

countObservers()

返回 Observable 对象的观察者数目。

void

deleteObserver(Observer o)

从对象的观察者集合中删除某个观察者。向此方法传递 null无效。

void

deleteObservers()

清除观察者列表,使此对象不再有任何观察者。

boolean

hasChanged()

测试对象是否改变。当且仅当在此对象上最近调用了 setChanged 方法时才返回 true;否则返回 false。

void

notifyObservers()

如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。

每个观察者都有其 update 方法,其调用参数有两个:observable 对象和 null。换句话说,此方法等效于: notifyObservers(null)

void

notifyObservers(Object arg)

如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。

每个观察者都有其 update 方法,其调用参数有两个:observable 对象和 arg 参数。 arg 可以是任意对象

protected  void

setChanged()

标记此Observable对象为已改变的对象;现在hasChanged方法将返回true。

关于发送通知的顺序

Observable 类中所提供的默认实现将按照其注册的重要性顺序来通知 Observers,但是子类可能改变此顺序,从而使用非固定顺序在单独的线程上发送通知,或者也可能保证其子类遵从其所选择的顺序。

注意:此通知机制与线程无关,并且与Object类的wait和notify机制完全独立。

新创建一个observable对象时,其观察者集是空的。当且仅当equals方法为两个观察者返回true时,才认为它们是相同的。

2.Oberver接口

这是个接口类,这个接口只有一个为实现的抽象方法update。实现该接口的对象成为观察者,该对象要实现update方法。注册了该对象(观察者)的对象(观察者)实例条用notifiyObservers方法后,观察者会自动执行update方法。

方法摘要

void

update(Observable o,Object arg)

只要改变了 observable 对象就调用此方法。

o - observable 对象。

arg - notifyObservers 方法的参数。

实例

该实例模拟了烧水的过程,涉及三个对象,Heater(热水器),Display(显示器),Alarm(报警器).

模拟过程:为了便于运行,水的初始化温度为90,沸点为95,显示器依据热水器显示温度,显示器显示温度为95时,报警器开始报警。明显可以看出Heater是subject ,Display 是它的 Obsrver,同时Display亦是subject,因为它要被报警器观察,所以Alarm是Display的Observer.

Heater.java类

publicclassHeaterextendsObservable {

privateinttemperature;

publicintgetTemperature() {

returntemperature;

}

publicvoidsetTemperature(inttemperature) {

this.temperature = temperature;

}

publicvoidboilWater() {

for(inti = 90; i < 110; i++) {

temperature = i;

this.setChanged();

this.notifyObservers();

}

}

}

Display.java类

publicclassDisplayextendsObservableimplementsObserver {

privateString status = "未开";

publicString getStatus() {

returnstatus;

}

publicvoidsetStatus(String status) {

this.status = status;

}

@Override

publicvoidupdate(Observable o, Object arg) {

this.displayTemperature(((Heater) o).getTemperature());

}

privatevoiddisplayTemperature(inttemperature) {

if(temperature > 100) {

this.setStatus("沸腾");

this.setChanged();

this.notifyObservers(temperature);

}

System.out.println("状态: " + status + "  现在温度: " + temperature);

}

}

Alarm.java类

publicclassAlarmimplementsObserver {

@Override

publicvoidupdate(Observable arg0, Object arg1) {

this.makeAlarm((Integer) arg1);

}

privatevoidmakeAlarm(inttemperature) {

System.out.println("嘀嘀嘀。。。水已经烧开了");

// System.out.println("现在水温是: " + temperature);

}

}

TestMain.java测试入口类

public class TestMain {

public static void main(String[] args) {

Heater heater = new Heater();

Display display = new Display();

Alarm alarm = new Alarm();

heater.addObserver(display);

display.addObserver(alarm);

heater.boilWater();

}

}

优点

支持松耦合和减少依赖性。客户端不再依赖于观察器,因为通过使用主体和 Observer 接口对客户端进行了隔离。许多框架具有此优点,在这些框架中的应用程序组件可以注册为当(低级)框架事件发生时得到通知。结果,框架将调用应用程序组件,但不会依赖于它。

观察器数目可变。观察器可以在运行时附加和分离,因为主体对于观察器数目没有任何假定。此功能在这样的情况下是很有用的:观察器数在设计时是未知的。例如,如果用户在应用程序中打开的每个窗口都需要一个观察器。

缺点

性能降低。在许多实现中,观察器的 update() 方法可能与主体在同一线程中执行。如果观察器列表很长,则执行 Notify() 方法可能需要很长时间。抽取对象依赖性并不意味着添加观察器对应用程序没有任何影响。

内存泄漏。在 Observer 中使用的回调机制(当对象注册为以后调用时)会产生一个常见的错误,从而导致内存泄漏,甚至是在托管的 C# 代码中。假定观察器超出作用范围,但忘记取消对主体的订阅,那么主体仍然保留对观察器的引用。此引用防止垃圾收集在主体对象也被破坏之前重新分配与观察器关联的内存。如果观察器的生存期比主体的生存期短得多(通常是这种情况),则会导致严重的内存泄漏。

隐藏的依赖项。观察器的使用将显式依赖性(通过方法调用)转变为隐式依赖性(通过观察器)。如果在整个应用程序中广泛地使用观察器,则开发人员几乎不可能通过查看源代码来了解所发生的事情。这样,就使得了解代码更改的含意非常困难。此问题随传播级别急剧增大(例如,充当 Subject 的观察器)。因此,应该仅在少数定义良好的交互(如 Model-View-Controller 模式中模型和视图之间的交互)中使用观察器。最好不要在域对象之间使用观察器。

测试/调试困难。尽管松耦合是一项重大的体系结构功能,但是它可以使开发更困难。将两个对象去耦的情况越多,在查看源代码或类的关系图时了解它们之间的依赖性就越难因此,仅当可以安全地忽略两个对象之间的关联时才应该将它们松耦合(例如,如果观察器没有副作用)。

参考文章:

http://baike.baidu.com/view/6547055.htm

http://msdn.microsoft.com/zh-cn/library/ms978753.aspx

沸点压力计算java_java 观察者模式相关推荐

  1. 阶乘的计算java_java中四种阶乘的计算

    package com.zf.s2;//创建一个包 import java.math.BigInteger;//导入类 import java.util.ArrayList; import java. ...

  2. 相似度计算 java_Java基于余弦方法实现的计算相似度算法示例

    Java基于余弦方法实现的计算相似度算法示例 引导语:Java 编程语言的风格十分接近C.C++语言.Java是一个纯的面向对象的程序设计语言,以下是小编整理的Java基于余弦方法实现的`计算相似度算 ...

  3. 元计算java_java 二元计算

    java 二元计算 关注:287  答案:1  mip版 解决时间 2021-01-09 05:23 提问者爱的苦涩 2021-01-08 20:17 借助命令行参数编写一个进行整数二元运算的应用程序 ...

  4. 埃及分数怎么计算java_JAVA代码—算法基础:埃及分数问题

    埃及分数问题 问题描述 分子为1 的分数称为埃及分数,现输入一个真分数,请将该分数按下面的方法分解为埃及分数: 1.若真分数的分子a能整除分母b,则真分数经过化简就可以得到埃及分数; 2.若真分数的分 ...

  5. 可视化计算java_Java可视化计算器

    今天更新Java可视化计算器,我的新浪微博:点击打开链接 ,没有测试图片,不过程序绝对正确,放心使用,我测试过了,c++版的请见:点击打开链接 package com.lzw06; import ja ...

  6. 沸点压力计算java_依据相律,恒沸混合物的沸点不随外压的改变而改变。

    [单选题]唐朝画家阎立本描绘唐太宗接见来迎文成公主入藏的吐蕃使者情景的作品 _______ . [简答题]"淮河文化"研究现状和特点是什么? [判断题]巴黎圣母院是著名的哥特式建筑 ...

  7. 智能跳过节假日算法java_java计算两个日期之前的天数实例(排除节假日和周末)...

    java计算两个日期之前的天数实例(排除节假日和周末) 发布时间:2020-09-02 23:07:01 来源:脚本之家 阅读:108 作者:jingxian 如题所说,计算两个日期之前的天数,排除节 ...

  8. observable java_java源码阅读Observable(观察者模式)

    1类签名和简介 packagejava.util;public class Observable Observable是Java内置的观察者模式中的主题类(没错,是类不是接口),和其对应的观察者接口是 ...

  9. 多个点 最远距离 java_Java实现的计算最大下标距离算法示例

    本文实例讲述了Java实现的计算最大下标距离算法.分享给大家供大家参考,具体如下: 题目描述 给定一个整形数组,找出最大下标距离j−i, 当且A[i] < A[j] 和 i < j 解法 ...

最新文章

  1. Linux grep 命令
  2. 北京交大计算机学院王浩业,双胞胎双双“吹”进北交大
  3. Data-truncation--Incorrect-string-value
  4. 第一章 python学习,个人对计算机硬件的一些理解
  5. 自然语言交流系统 phxnet团队 创新实训 项目博客 (五)
  6. 最常用的设计模式---适配器模式(C++实现)
  7. 前端学习(3253):react脚手架文件介绍
  8. 3.2_ 1_ 虚拟内存的基本概念
  9. wordpress模板-单栏多色调全站pajx个人博客模板 idevs主题
  10. linux下mknod命令介绍
  11. python中什么是异常,python中异常处理,python异常处理,什么是异常?异常是一
  12. android零基础教程,Android零基础入门|Activity初入门,创建和配置如此简单
  13. unity虚拟摇杆控制的实现
  14. 云课堂计算机教师,校校云课堂教师端
  15. Matlab聚类分析相关函数
  16. SIM868——GPS加速定位方法
  17. 2021年计算机保研面试题
  18. Android acra 日志上报,android acra错误日志上报
  19. 最近看中的几款Limitless的家具
  20. 近源社工-校内网渗透测试

热门文章

  1. [转载] 变形金刚1
  2. 分布式事物解决方案-TCC
  3. 完美解决ie8以下不兼容h5的方法
  4. Hash算法解决冲突的四种方法
  5. .gitignore和.gitkeep有什么区别?
  6. map(&:name)在Ruby中是什么意思?
  7. 如何在Git中更改多次提交的作者和提交者名称以及电子邮件?
  8. 导出数据库数据成txt格式
  9. SpringBoot引用lombok让代码更简洁
  10. IPFS Series -- Bitswap Protocol