对于观察者模式,其实Java已经为我们提供了已有的接口和类。对于订阅者(Subscribe,观察者)Java为我们提供了一个接口,JDK源码如下:

 package java.util;

 public interface Observer {
void update(Observable o, Object arg);
}

和我们上一篇实现的观察者一样,仅提供一个update方法用于接收通知者的通知做出相应改变。

我们再来看看Java为我们提供了一个怎样的通知者(Publish,发布者),JDK源码如下:

 package java.util;

 public class Observable {
private boolean changed = false;  //是否改变状态
private Vector obs;    //Vector利用同步方法来线程安全,线程安全在多线程情况下不会造成数据混乱 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();  //将Vector转换成数组
clearChanged();    //重置状态
} 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();
}
}

不得不说,Java源码考虑得就是比自己写的要好。首先,使用Vector,Vector相比于ArrayList来说,它是线程安全的。其次,在添加和删除观察者时对两个方法使用了synchronized关键字,这都是在为多线程考虑。确实Java源码并不是那么可怕,它同样也是由一些最简单最基础的组合而来。

接下来我们来看看是如何利用Java提供的接口和方法来实现观察者模式。

 package day_10_observer_jdk;

 import java.util.Observable;
import java.util.Observer; /**
* 实现java.util.Observer接口的观察者
* @author turbo
*
* 2016年9月14日
*/
public class Subscribe implements Observer { public Subscribe(Observable o){
o.addObserver(this); //将该观察者放入待通知观察者里
}
/* (non-Javadoc)
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(Observable o, Object arg) {
System.out.println("收到通知:" + ((Publish)o).getData());
} }
 package day_10_observer_jdk;

 import java.util.Observable;

 /**
* 继承java.util.Observable的通知者
* @author turbo
*
* 2016年9月14日
*/
public class Publish extends Observable {
private String data = ""; public String getData() {
return data;
} public void setData(String data) {
if (!this.data.equals(data)){
this.data = data;
setChanged(); //改变通知者的状态
}
notifyObservers(); //调用父类Observable方法,通知所有观察者
}
}

客户端测试代码:

 package day_10_observer_jdk;

 /**
* @author turbo
*
* 2016年9月14日
*/
public class Main { /**
* @param args
*/
public static void main(String[] args) {
Publish publish = new Publish();
Subscribe subscribe = new Subscribe(publish); publish.setData("开始");
} }

这样我们就利用了Java给我们提供的Observer接口和Observable类实现了观察者模式。上一篇我们提到了事件委托,我们在下一篇来了解一下什么是事件委托。

利用Java提供的Observer接口和Observable类实现观察者模式的更多相关文章

  1. Java Observer接口和Observable类实现观察者模式

    对于观察者模式,其实Java已经为我们提供了已有的接口和类.对于订阅者(Subscribe,观察者)Java为我们提供了一个接口,JDK源码如下: package java.util; public ...

  2. Java中使用Observer接口和Observable类实践Observer观察者模式

    在Java中通过Observable类和Observer接口实现了观察者模式.实现Observer接口的对象是观察者,继承Observable的对象是被观察者. 1. 实现观察者模式 实现观察者模式非 ...

  3. 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)

    最近看老罗的视频,跟着完成了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口 ...

  4. 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包括增删改查、JavaBean反射原理,附源代码)

    近期看老罗的视频,跟着完毕了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完毕对数据库的增删改查.当中查询这块,包含普通的查询和利用反射完毕的查询,主要包含以下几个函数接口 ...

  5. java 多线程:Callable接口;FutureTask类实现对象【Thread、Runnable、Callable三种方式实现多线程的区别】

    Callable接口介绍: Java5开始,Java提供了Callable接口,像是Runnable接口的增强版,Callable接口提供了一个 call()方法可以作为线执行体. call()方法比 ...

  6. Java常用类库--观察者设计模式( Observable类Observer接口)

    如果要想实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口. import java.util.* ; class House extends Obse ...

  7. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  8. java学习——JDK1.8接口和实现类

    Java 8 新特性:接口的静态方法和默认方法 https://blog.csdn.net/sun_promise/article/details/51220518 接口的默认方法和静态方法 http ...

  9. Java学习笔记_22_Set接口的实现类

    22.Set接口的实现类: Set接口存放的元素是无序的且不包括反复元素. 1>实现类HashSet: HashSet类依据元素的哈希码进行存放,取出时也能够依据哈希码高速找到.HashSet不 ...

随机推荐

  1. 转载八个最佳Python IDE

    八个最佳Python IDE 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Python是一种功能强大.语言简洁的编程语言.本文向大家推荐8个适合Pyt ...

  2. centos 6.5 搭建ftp服务器

    linux下一般使用vsftpd作为ftp服务器. vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序.特点是小巧轻快,安全易用. 下面是安装配置步骤: 1.安装vsftpd yum i ...

  3. piwik安装部署最佳实践

    1.piwik介绍 Piwik是一个PHP和MySQL的开放源代码的Web统计软件,它给你一些关于你的网站的实用统计报告,比如网页浏览人数,访问最多的页面,搜索引擎关键词等等. Piwik拥有众多不同 ...

  4. Object-C开发常用宏定义

    Object-C开发中宏会将经常用到的系统常量进行封装,方便使用: 1.获取通知中心 #define EYNotificationCenter(name, object, userInfo) [[NS ...

  5. [SinGuLaRiTy] 数论基础

    [SinGuLaRiTy-1004] Copyright (c) SinGuLaRiTy 2017 . All Rights Reserved. 整除: 设a,b为整数,且a不为0,如果存在一个整数q ...

  6. Python os与sys模块解析

    os与sys模块的官方解释如下: os: This module provides a portable way of using operating system dependent functio ...

  7. HibernateTemplate的使用

    HibernateTemplate 提供了非常多的常用方法来完成基本的操作,比如增加.删除.修改及查询等操作,Spring 2.0 更增加对命名 SQL 查询的支持,也增加对分页的支持.大部分情况下, ...

  8. 4 安装MPush

    cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 一.Linux安装Mpush [root@loca ...

  9. java多线程基本概述(十三)——Executor

    1:Executor接口 public interface Executor 执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等 ...

  10. IE和其他浏览器用JS新窗口打开的问题

    Chrome中 window.open(pageURL,name,parameters) pageURL 为子窗口路径 name 为子窗口句柄 parameters 为窗口参数(各参数用逗号分隔) 例 ...