Java设计模式 - 观察者模式
定义
观察者模式属于对象行为型模式。
在对象之间定义一对多的依赖,这样一来当一个对象改变状态,依赖它的对象都会收到通知并自动更新。
优点
1、 主题和观察者之间抽象耦合。无论什么对象主要实现了特定的接口(如本文中的Observable),就可以成为观察者对象。
2、 支持广播通信。就像一个播音员不需要知道谁在收听她的播音,只负责播音,而听不听就是听众的事了。这相当于给了你在任何时候都可以增加或者删除观察者的自由。
适用范围
当对象之间是一种一对多的关系时。好比有一份文件要同时分发给多个人。
模式结构
各个角色的作用:
Subject(主题):目标知道它的观察者。可以有任意多个观察者观察同一个目标;提供注册和删除观察者对象的接口。
Observer(观察者):为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject(具体的主题):当它的状态发生改变时,向它的各个观察者发出通知。
ConcreteObserver(具体观察者):实现Oberserver的更新接口以使自身状态与目标状态一致。
UML图

两种方式:
1、(推)主题对象主动推送;
2、(拉)主题对象通知观察者,观察者自己去获取需要的信息;
这两种方式会在下面介绍。
例子
写一个简单的程序来说明问题:假如现在有一个广播站在播音,有许多收音机在收听。
面向接口编程能够利用多态,从而降低对象之间的耦合度。
package com.tony.observer; /**
* 具体的主题类必须实现这个接口
*
*/
public interface Subject { //注册观察者
public void register(Observable observer);
//移除观察者
public void remove(Observable observer);
//推送消息
public void update(String message); }
package com.tony.observer; import java.util.ArrayList;
import java.util.List; /**
* 相当于ConcreteSubject,具体的主题类
*
*/
public class Radiostation implements Subject{ private List<Observable> observers; public Radiostation(){
observers = new ArrayList<Observable>();
} public void register(Observable observer){
observers.add(observer);
System.out.println("have "+observers.size()+" observer are listening...");
} public void remove(Observable observer){
observers.remove(observer);
System.out.println("a observer has gone...left "+observers.size()+" observer");
} public void update(String message){
for(Observable observer:observers){
observer.update(message);
}
}
}
package com.tony.observer; /**
* 相当于Observer,所有的观察者必须实现这个接口
*
*/ public interface Observable { //更新数据
public void update(String message);
//成为主题对象的观察者,开始监听
public void register();
//不再监听主题对象
public void remove(); }
package com.tony.observer; /**
* 相当于ConcreteObserver,观察者对象
*
*/
public class Radio implements Observable { private Subject subject; public Radio(Subject subject){
this.subject = subject;
} @Override
public void update(String message) {
display(message);
} @Override
public void register() {
subject.register(this);
} @Override
public void remove() {
subject.remove(this);
} public void display(String message){
System.out.println("get message from radiostation:"+message);
} }
package com.tony.observer;
/**
* 测试观察者模式
*
*/
public class Test {
public static void main(String[] args) { Subject radiostation = new Radiostation(); Radio o1 = new Radio(radiostation);
Radio o2 = new Radio(radiostation); //注册
o1.register();
o2.register(); //更新消息
radiostation.update("hello world");
radiostation.update("over"); //退出监听
o1.remove();
o2.remove();
}
}
运行结果:

这种实现方法属于“推”:主题主动将数据推送给观察者。其实还有另外一种叫做“拉”的方式:主题不主动将数据推送给观察者,只是给它们一个更新提示,接收的权利在观察者手上!
与“拉”相比较,“推”有个很大的缺点:当推送的数据量很大的时候,会对程序运行性能产生影响!就像安卓手机某些后台应用:不经过你的同意自动将服务器中的一些数据下载的你的手机上。而“拉”这种方式就没有这样的情况,就好像你关注的公众号一样:给你推送消息时并没有把所有内容都推送过来,只是把一个标题发给你,想不想看在于你。
但是”推“这种方式比较符合设计模式的原则,所以一般使用的都是这种方式。
总结
观察者模式应用很广,不仅在你写代码的时候用到,你在生活当中也时常能够遇到:比如走在校园里收听到的广播:广播站是主题,你就是观察者。当你进入到能够听见广播的范围时,你就成了一个观察者:播音主持说的话就是要更新的数据,通过广播站这个主题将数据发送给你们,你们负责收听。
必须能够熟练使用。
其他模式:设计模式专栏
参考文献
《Head First 设计模式》
《设计模式》
Java设计模式 - 观察者模式的更多相关文章
- java设计模式--观察者模式(Observer)
java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...
- 【设计模式】Java设计模式 - 观察者模式
[设计模式]Java设计模式 - 观察者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 @一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长 ...
- JAVA 设计模式 观察者模式
用途 观察者模式 (Observer) 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象. 这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 观 ...
- Java设计模式--观察者模式到监听器
观察者模式是对象的行为模式.又叫做发布-订阅模式.模型-视图模式.源-监听器模式. 抽象主题角色:主题角色将所有对观察者对象的引用到保存在一个集合里,每个主题都可以拥有任意数量的观察者.抽象主题提供一 ...
- Java设计模式の观察者模式(推拉模型)
目录: 一.观察者定义 二.观察者模式的结构(推模式实现) 三.推模型和拉模型(拉模式实现) 四.JAVA提供的对观察者模式的支持 五.使用JAVA对观察者模式的支持(自带推模式实现实例) 一.观察者 ...
- 我的Java设计模式-观察者模式
相信大家都有看过<喜洋洋与灰太狼>,说的是灰太狼和羊族的"斗争",而每次的结果都是灰太狼一飞冲天,伴随着一句"我还会回来的......".为灰太狼感 ...
- java设计模式-观察者模式学习
最近学习了设计模式中的观察者模式,在这里记录下学习成果. 观察者模式,个人理解:就是一个一对多模型,一个主体做了事情,其余多个主体都可以观察到.只不过这个主体可以决定谁去观察他,以及做什么事情可以给别 ...
- Java设计模式——观察者模式(事件监听)
最近在看Tomcat和Spring的源码,在启动的时候注册了各种Listener,事件触发的时候就执行,这里就用到了设计模式中的观察者模式. 引-GUI中的事件监听 想想以前在学Java的GUI编程的 ...
- JAVA设计模式—观察者模式和Reactor反应堆模式
被观察者(主题)接口 定义主题对象接口 /**抽象主题角色: 这个主题对象在状态上发生变化时,会通知所有观察者对象 也叫事件对象 */ public interface Subject { //增加一 ...
随机推荐
- tomcat中server.xml配置详解
Tomcat Server的结构图如下: 该文件描述了如何启动Tomcat Server <Server> <Listener /> <GlobaNami ...
- hdu-1213-How Many Tables
How Many Tables Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- JS json的使用
json的定义 json能够通过4种基本数据类型以及2种结构化数据表示 字符串 "footbar" 不能使用单引号 数值 125.4 只支持10进制 布尔 true fals ...
- centos6配置vnc登录远程物理机及vb复制vdi启动虚拟机网络问题
1.安装vnc和vncserver #yum install tigervnc tigervnc-server 2.启动VNC服务# vncserverYou will require a passw ...
- 性能测试学习之二 ——性能测试模型(PV计算模型)
PV计算模型 现有的PV计算公式是: 每台服务器每秒平均PV量 =( (总PV*80%)/(24*60*60*40%))/服务器数量 =2*(总PV)/* (24*60*60) /服务器数量 通过定积 ...
- 定时任务服务 CronService使用说明
CronServiceInstaller.exe 部署安装程序 1.在打开该程序前务必设置为管理员运行 2.点击注册服务 3.检查服务是否开启,点击 services.msc, 打开系统服务列表 4 ...
- 64位系统使用Access 数据库文件的彻底解决方法
最近,有PDF.NET用户问我怎么在64位系统下无法访问Access数据库的问题,我第一反应是我怎么没有遇到呢?今天一看自己的VS和Office都是32位版本的,所以在VS里面调试访问Access是没 ...
- Visual Studio Code 使用 ESLint 增强代码风格检查
前言 在团队协作开发中,为了统一代码风格,避免一些低级错误,应该设有团队成员统一遵守的编码规范.很多语言都提供了Lint工具来实现这样的功能,JavaScript也有类似的工具:ESLint.除了可以 ...
- jQuery原型方法first,last,eq,slice源码分析
这4个方法中前3个方法很常用大家都见过,但是slice方法可能会以为是数组方法,其实slice也是jQuery的一个原型方法,只不过是底层方法是为其他方法服务的(更具体点是为eq方法服务的),首先还是 ...
- CSS3 学习笔记
border-radius 圆角是做网页永远绕不过的话题,以前基本是通过背景图片做的,有了 CSS3 以后通过属性就 能够搞定,我们可以通过 border-radius 设置元素的圆角半径. bord ...