java设计模式--观察者模式和事件监听器模式
观察者模式
观察者模式又称为订阅—发布模式,在此模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来事件处理系统。。
基于事件驱动机制的系统或语言,比如node.js、nio等,不难发现其最终的基础模式就是观察者模式,只是不同的应用场景,也会有各自不同的侧重。
观察者
class Watcher implements java.util.Observer {
public void update(java.util.Observable obj, Object arg) {
System.out.println("Update() called, count is "
+ ((Integer) arg).intValue());
}
}
被观察者
class BeingWatched extends java.util.Observable {
void counter(int period) {
for(; period>=0; period-- ) {
setChanged();
notifyObservers(new Integer(period));
try {
Thread.sleep(100);
} catch( InterruptedException e) {
System.out.println("Sleep interrupeted" );
}
}
}
}
测试
public class ObserverDemo {
public static void main(String[] args) {
BeingWatched beingWatched = new BeingWatched();//受查者
Watcher watcher = new Watcher();//观察者
beingWatched.addObserver(watcher);
beingWatched.counter(10);
}
}
监听器模式
事件源经过事件的封装传给监听器,当事件源触发事件后,监听器接收到事件对象可以回调事件的方法
1、首要定义事件源对象(事件源相当于单击按钮事件当中的按钮对象、属于被监听者):
public class DemoSource {
private Vector repository = new Vector();//监听自己的监听器队列
public DemoSource(){}
public void addDemoListener(DemoListener dl) {
repository.addElement(dl);
}
public void notifyDemoEvent() {//通知所有的监听器
Enumeration enum = repository.elements();
while(enum.hasMoreElements()) {
DemoListener dl = (DemoListener)enum.nextElement();
dl.handleEvent(new DemoEvent(this));
}
}
}
2、其次定义事件(状态)对象(该事件对象包装了事件源对象、作为参数传递给监听器、很薄的一层包装类):
public class DemoEvent extends java.util.EventObject {
public DemoEvent(Object source) {
/**
* source—事件源对象—如在界面上发生的点击按钮事件中的按钮 所有 Event 在构造时都引用了对象 "source",在逻辑上认为该对象是最初发生有关 Event 的对象
*/
super(source);
}
public void say() {
System.out.println("This is say method...");
}
}
3、最后定义我们的事件侦听器接口如下
public interface DemoListener extends java.util.EventListener {
/**
* EventListener是所有事件侦听器接口必须扩展的标记接口、因为它是无内容的标记接口、
*
* 所以事件处理方法由我们自己声明如下:
* @param dm
*/
public void handleEvent(DemoEvent dm);
}
监听器实现类
public class DemoListener1 implements DemoListener {
public void handleEvent(DemoEvent de) {
System.out.println("Inside listener1...");
de.say();//回调
}
}
4、测试代码
public class TestDemo {
DemoSource ds;
public TestDemo(){
try{
ds = new DemoSource();
//将监听器在事件源对象中登记:
DemoListener1 listener1 = new DemoListener1();
ds.addDemoListener(listener1);
ds.addDemoListener(new DemoListener() {
public void handleEvent(DemoEvent event) {
System.out.println("Method come from 匿名类...");
}
});
ds.notifyDemoEvent();//触发事件、通知监听器
}catch(Exception ex){
ex.printStackTrace();
}
}
public static void main(String args[]) {
new TestDemo();
}
}
总结
1、Observer的实现相对简单,event-listener需要实现三个角色,observer-observable需要实现两个角色。
2、Observable的api已经把对观察者的注册,删除等定义好了,而且是线程安全的。而event-listener需要使用者自己实现。
3、两者都需要自己定义并实现触发事件的通知。但Observable需要注意要在通知Observer之前调用jdk提供的setChanged()。
4、event-listener是传统的c/s界面事件模型,分事件源和事件(状态)角色,事件源要经过事件的包装、成为事件的属性之一再传递给事件监听/处理者,这个事件监听者就相当于观察者。Observer更简洁一些。两者在思想上是统一的,很多框架仍然使用了event-listener模式,比如spring框架的ApplicationEvent,ApplicationListener。
5、监听器模式是观察者模式的另一种形态,同样基于事件驱动模型。监听器模式更加灵活,可以对不同事件作出相应。但也是付出了系统的复杂性作为代价的,因为我们要为每一个事件源定制一个监听器以及事件,这会增加系统的负担。
发布订阅
观察者模式实现发布订阅,可以添加一个调度中心,降低publisher和subscriber的耦合,具体实现中,有两个版本。
1) 拉模式:目标角色在发生变化后,仅仅告诉观察者角色“我变化了”;观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。拉模式是想要就主动表白获取。
2) 推模式:通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。推模式是管你要不要,先给你啦。
这两种模式的使用,取决于系统设计时的需要。如果目标角色比较复杂,并且观察者角色进行更新时必须得到一些具体变化的信息,则“推模式”比较合适。如果目标角色比较简单,则“拉模式”就很合适啦。
事件和消息的区别
事件本身即是具有特定业务含义的一种固定结构对象,而消息是数据传输过程中的载体。概念上宽泛来讲,事件可以称作是一种消息,而消息不能代替事件。事件反映的是特定的业务状态,比如订单创建、服务调用失败、应用宕机等。
一个事件对象描述的是谁在什么时间做了什么事情,看到这个对象,我们就能知道是发生了什么特定的事情。但是事件对象本身不承载数据传递的职能。
消息中间件实现的是消息的存储,解决的是解耦上下游业务系统。事件处理系统是更多的侧重对事件的分析处理,并驱动业务的进一步扭转。
java设计模式--观察者模式和事件监听器模式的更多相关文章
- Java设计模式——观察者模式(事件监听)
最近在看Tomcat和Spring的源码,在启动的时候注册了各种Listener,事件触发的时候就执行,这里就用到了设计模式中的观察者模式. 引-GUI中的事件监听 想想以前在学Java的GUI编程的 ...
- java设计模式-观察者模式,装饰者模式
1.1定义 慨念:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 即:主题和观察者定义了一对多的关系,观察者依赖于主题,只要主题发生变化,观察者就 ...
- JAVA设计模式—观察者模式和Reactor反应堆模式
被观察者(主题)接口 定义主题对象接口 /**抽象主题角色: 这个主题对象在状态上发生变化时,会通知所有观察者对象 也叫事件对象 */ public interface Subject { //增加一 ...
- Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)
一.回调函数 为什么首先会讲回调函数呢?因为这个是理解监听器.观察者模式的关键. 什么是回调函数 所谓的回调,用于回调的函数. 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数. ...
- Java设计模式(10)代理模式(Proxy模式)
理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...
- Java设计模式之《职责链模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6530089.html 职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形 ...
- Java设计模式之《享元模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6542449.html 享元模式:"享"就是分享之意,指一物被众人共享, ...
- Java设计模式之《调停者模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6518603.html 调停者模式. 我们想象一下这样的场景:一个系统内部通过许多的类互相之 ...
- java设计模式--观察者模式(Observer)
java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...
随机推荐
- 使用nodejs+http(s)+events+cheerio+iconv-lite爬取2717网站图片数据到本地文件夹
源代码如下: //(node:9240) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' ...
- Oracle系列七 子查询
子查询语法 SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table); 子查询 (内查询) 在 ...
- excel VBA 密码设置问题
Excel中VBA设置密码的步骤如下: 1.右键点击任何工作表,选择VBAProject属性: 2.在新对话框总,选择“保护”选项卡: 3.勾选查看时锁定,输入密码即可.
- 制作Visual Studio 2017 (VS 2017) 离线安装包 (转)
史上功能最强大的Visual Studio 2017版本发布,但是由于版本更新速度加快和与第三方工具包集成的原因,微软研发团队没有为这个版本提供离线下载的安装文件.如果用户处在一个与外网隔离的网络环境 ...
- 【电商日志项目之五】数据分析-MR方式
环境 hadoop-2.6.5 hbase-0.98.12.1-hadoop2 新增用户指标分析(1)用户分析模块 (2)浏览器分析模块 根据分析效果图,找出分析的维度:用户分析是指某个时间段内的数量 ...
- 【Python学习之五】函数
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 Python不但能非常灵活地定义函数,而且本身内置 ...
- 算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串
最近在学习java,但是对于数据操作那部分还是不熟悉 因此决定找几个简单的算法写,用php和java分别实现 1.合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两 ...
- Linux thread process and kernel mode and user mode page table
Linux 中线程和进程切换的开销: Linux 操作系统层面的进程和线程的实现都是task_struct描述符. task_struct 包含成员变量:内核态stack. 这些都存在3-4G虚拟地 ...
- 什么是渐进式Web App(PWA)?为什么值得关注?
转载自:https://blog.csdn.net/mogoweb/article/details/79029651 在开始PWA这个话题之前,我们先来看看Internet现状. 截至2017年1月, ...
- Automatically generating nice graphs at end of your Load Test with Apache JMeter and JMeter-Plugins
Update as of November 2017: Since JMeter 3.0, last version being 3.3, JMeter provides Out Of The Box ...