一、简介

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

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

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

二、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中提供的排序方式

    package com.bjpowernode.t01; import java.util.Arrays; /** * 使用jdk中提供的排序方式 * */public class TestArray ...

  2. 关于Java JDK中 URLDecoder.decode 方法

    java.net.URLDecoder.decode 在项目中碰到了个比较奇怪的问题,就是我在本地使用java.net.URLDecoder.decode(ruleName)方法解码,没有问题,本地的 ...

  3. java jdk中安装证书的步骤

    需要注意的是:导入证书时,请确认导入的JDK为当前程序运行所用的JDK,且路径是jdk目录下的jre目录路径,非与jdk同级的jre目录 首先你可以把需要导入的证书放在keytool的同级目录下,然后 ...

  4. java jdk 中HashMap的源码解读

    HashMap是我们在日常写代码时最常用到的一个数据结构,它为我们提供key-value形式的数据存储.同时,它的查询,插入效率都非常高. 在之前的排序算法总结里面里,我大致学习了HashMap的实现 ...

  5. [JAVA]SpringBoot中让接口支持跨域

    官方原文:https://spring.io/blog/2015/06/08/cors-support-in-spring-framework ===抽空翻译 最简单办法:在方法上增加注解: @Cro ...

  6. Eclipse建立Java工程中的三个JRE选项的区别(Use an execution environment JRE,Use a project specific JRE,Use default JRE)

    本博客部分转载自: http://blog.csdn.net/wdjhzw/article/details/42086615  这篇博客写的非常好,很用心. 一.首先看新建Java Project时候 ...

  7. JDK中的Timer和TimerTask详解(zhuan)

    http://www.cnblogs.com/lingiu/p/3782813.html ************************************************** 目录结构 ...

  8. Java 7 中 NIO.2 的使用——第一节 Path 类的使用

    路径隶属于文件系统,实际上它是存储和组织媒体文件的格式,通常在一块或多块硬盘设备上,以便于非常容易地检索.文件系统可以通过  java.nio.file.FileSystems 这个final 类来访 ...

  9. Java JDK 1.7 和 JDK 1.8 新特性

    0 引言 本文主要介绍 Java JDK 中 1.7 和 1.8 的新特性. 1 JDK 1.7 新特性 1. switch可以接受String类型: public class Switch { pu ...

随机推荐

  1. TinyFox在VS2015上的调试器

    这个一个TinyFox在VS2015上的调试工具 : 开源了 https://github.com/maxzhang1985/TinyFoxDEBUG 开发这个工具的初衷,是想更便捷的调试Nancy ...

  2. String-------RegularHelper

    /// <summary> /// 正则表达式相关方法集合 /// </summary> public static class RegularHelper { private ...

  3. UIApplication和delegate代理

    所有的移动操作系统都有个致命的缺点:app很容易受到打扰,比如一个来电或者锁屏都会导致app进入后台甚至被终止 还有很多其他类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统事件,这是 ...

  4. 0422 Step2-FCFS调度

    一.目的和要求 1. 实验目的 (1)加深对作业调度算法的理解: (2)进行程序设计的训练. 2.实验要求 用高级语言编写一个或多个作业调度的模拟程序. 单道批处理系统的作业调度程序.作业一投入运行, ...

  5. NPOI根据模板生成chart图表导出Excel

    导入NPOI的全部dll. 因为NPOI的API里面还没有对于Chart图表方面的操作,所以只能根据提示做好的图表作为模板,修改数据源的方法来改变图表. 注意:NPOI要用2003版以下的excel才 ...

  6. JS Date.Format

    // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 个占 ...

  7. C#基本概念列举说明

    1. 关键字      在C#代码中常常使用关键字,关键字也叫保留字,是对C#有特定意义的字符串.关键字在Visual Studio 环境的代码视图中默认以蓝色显示.例如,代码中的using.name ...

  8. visual studio 2013 配置开发环境

    https://www.visualstudio.com/explore/xamarin-vs http://sourceforge.net/projects/easyeclipse/files/?s ...

  9. 做java工作整整1年了,看到了大牛的奋斗历程,我感觉自己又有目标了

    2014年6月,刚刚踏上社会那会儿,我记得我第一次面试啥都不知道,穿的也不修边幅去应聘一家4s销售,面试官看到我,我明细感觉到了对方厌恶的神色,这是我上社会的第一课,找工作不管是什么工作,衣着得体,是 ...

  10. 利用PBfunc在Powerbuilder中使用https获取微信的AccessToken

    在前篇中讲解了使用PBFunc在Powerbuilder自己进行http的GET和POST操作. 本篇简单用代码演示下https的微信AccessToken的获取: n_pbfunc_http lnv ...