一、简介

观察者设计模式有如下四个角色

  • 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现,也可以使用非抽象类来实现。
  • 具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
  • 抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
  • 具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。通常用一个子类实现。

  观察者设计模式类图如下:

二、java JDK中对观察者的支持
  java JDK中提供了Observer 与 Observable两个类。Observer类可以看作是抽象观察者角色,而Observable是抽象主题角色。

  1、Objserver

    Objserver 是个接口,代码如下:

public interface Observer {/*** 该方法当主题对象发生改变的时候被调用. An* 一个应用调用主题对象的notifyObservers方法来application calls an <tt>Observable</tt> object's* <code>notifyObservers</code> method to have all the object's* observers notified of the change.** @param   o     the observable object.* @param   arg   an argument passed to the <code>notifyObservers</code>*                 method.*/void update(Observable o, Object arg);
}

  它只提供了一个update,让子类去实现。当主题对象发生改变的时候,就会调用观察者对象的update方法,从而达到观察者发生改变的目的。

  2、Observable

    Observable是个类,代码如下:

public class Observable {private boolean changed = false;private Vector obs;//用于存放观察者对象的引用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) { if (!changed)//当状态没有发生改变的时候,直接返回return;arrLocal = obs.toArray();clearChanged();}//通知并调用观察者的update方法for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);} //移除所有观察者public synchronized void deleteObservers() {obs.removeAllElements();} //设置状态改变protected synchronized void setChanged() {changed = true;} //重置状态protected synchronized void clearChanged() {changed = false;}//判断是否状态是否发生改变public synchronized boolean hasChanged() {return changed;}返回观察者的个数public synchronized int countObservers() {return obs.size();}
}

  从代码可以看出,我们可以让具体主题对象继承Observable类,具体观察者对象实现Observer接口并实现update方法。调用的时候只需要实例化具体主题对象与具体观察者对象,然后将具体观察者对象添加到具体主题对象中的obs(Vector)列表。当具体主题对象的状态发生该变时,调用观察者对象的update方法(这里状态发生该变指的是调用主题对象的某个方法,该方法里面有对具体观察者对象的update方法的调用)。

三、实例

  具体观察者对象

具体主题对象
package com.observer;import java.util.Observable;
/*** 具体主题对象**/
public class ConcreteSubject extends Observable {private String info;public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}public void doSomething(String str) {System.out.println("subject: " + str);setInfo(str);setChanged();//改变主题对象的状态,这里如果不改变它的状态,则不会对观察者对象调用update方法
//        notifyObservers();//也可以不传递参数notifyObservers("subject is changed");//这里传递的参数是观察者对象中update方法参数列表中的第二个参数
    }
}

  具体观察者对象

package com.observer;import java.util.Observable;
import java.util.Observer;
/*** 具体观察者对象**/
public class ConcreteObserver implements Observer {/*** @param subject  具体主题对象* @param arg notifyObservers(String str) 传递的参数*/public void update(Observable o, Object arg) {System.out.println(arg);ConcreteSubject subject = (ConcreteSubject)o;System.out.println("observer: " + subject.getInfo());}
} 

  调用代码:

package com.observer;import java.util.Observer;public class Test {public static void main(String[] args) {//观察者对象Observer observer = new ConcreteObserver();Observer observer2 = new ConcreteObserver();Observer observer3 = new ConcreteObserver();//主体对象ConcreteSubject observable = new ConcreteSubject();//观察者加入主题对象汇总的观察者列表
        observable.addObserver(observer);observable.addObserver(observer2);observable.addObserver(observer3);//主体对象发生改变observable.doSomething("happy");observable.doSomething("sad");}
}

                                                 

观察者模式--java jdk中提供的支持相关推荐

  1. JDK中提供的实现——通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例

    JDK中提供的实现 在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例. 1 ...

  2. Java JDK中几个经典的版本

    Java JDK中几个经典的版本 1. 1995年05月23日 JDK 1.0 版发布,于1996年JDK正式提供下载,标志着Java的诞生. 2. 1998年12月04日 JDK 1.2 版发布,而 ...

  3. Java黑皮书课后题第10章:**10.23(实现String类)在Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString2)

    **10.23(实现String类)在Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString2) 题目 简短的吐槽 代码:这里将类名改用Test23_MyStrin ...

  4. java logging包_用JDK中提供的java.util.logging.*包创建Logger对象----原创

    由于项目中用到了Applet与Servlet之间(客户端用Applet.Server端用Servlet)的通信,要求: 1:>客户端与服务端必须出Log. 2:>浏览器在加载Applet时 ...

  5. java ssl证书生成_java – 使用jdk中提供的keytool生成SSL证书

    我在Web应用程序中使用的密钥库文件已于上周过期.我很久以前就生成了它.所以我开始使用keytool生成新证书.我使用此证书连接事务服务器和Web服务器.我想为此应用程序使用自签名证书.我使用以下命令 ...

  6. Java jdk中的部分工具javac javaw javaws javadoc javah javap jar jdb jps的作用

    一.JDK 工具和实用程序 JDK提供的标准工具和程序 基本工具:javac, java, javadoc, apt, appletviewer, jar, jdb, javah, javap, ex ...

  7. jdk中提供的Collection、Collections、Collector、Collectors你分的清楚?

    初次一看四个有点相似,而且有些时候一不小心还真有可能敲错,因为喜欢代码提示没仔细看提示,结果通过.去调用结果发现没有找到你想用的方法.所以写代码的时候需要注意一点这个区别 Collections.em ...

  8. java jdk中的归并排序实现

    在Arrays.java中的sort中 public static void sort(Object[] a, int fromIndex, int toIndex) {if (LegacyMerge ...

  9. Java黑皮书课后题第10章:10.24(实现Character类)在Java库中提供了Character类,给出你自己对这个类的实现(将新类命名为MyCharacter)

    代码解释 这里为区分不同题目,类名更改为Test24_MyCharacter.java 破题 这里的"破"和之前写的不太一样,不是动词,不是解决问题的意思 而是形容词 很明显这道题 ...

最新文章

  1. python实现 “不带中括号”输出列表中的数据
  2. python函数拟合不规则曲线_python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案...
  3. Vue.js 使用 Swiper.js 在 iOS 11 时出现错误
  4. 2021年春季学期-信号与系统-第八次作业参考答案-第六小题
  5. avalon数据已更新,视图未更新的bug修复
  6. python编程从入门到实践读书笔记-《Python编程:从入门到实践》项目部分读书笔记(二)...
  7. 宁波python学习_python学习第十五天
  8. dict格式转字符串两种方法的区别
  9. Python学习之函数返回多个值
  10. 5分钟了解TypeScript
  11. 100g流量在电脑上可以用多久_三大运营商5G体验方案出炉!100G一个月够不够?...
  12. redis api 中文文档_我的Redis学习资料库
  13. Hive 分区表操作 创建、删除
  14. 基于live555开发嵌入式linux系统的rtsp直播服务
  15. sqlserver200864位下载_SQL2008下载 SQL Server 2008 R2 简体中文版(64位) 下载-脚本之家
  16. Windows平台下使用GoLand生成Linux可执行文件
  17. 谷歌打开微信定位服务器地址,使用Chrome修改user agent模拟微信内置浏览器
  18. (转)粒子编辑器Particle designer属性的介绍
  19. python 作用域知识点整理
  20. Linux错误:bash:finger 未找到命令...

热门文章

  1. PHP三维数组变一维
  2. RocketMQ消息存储原理
  3. ​同样更新分支,git merge 和 rebase 有什么区别?
  4. 单调栈解决维持相对位置不变最小/最大字典序问题
  5. JAVA内存模型与线程安全
  6. ios平台实现局域网ip扫描
  7. 【跃迁之路】【593天】程序员高效学习方法论探索系列(实验阶段350-2018.09.21)...
  8. FTP(二)ftp部署与防火墙配置
  9. Docker 的两类存储资源 - 每天5分钟玩转 Docker 容器技术(38)
  10. centos 7下Hadoop 2.7.2 伪分布式安装