最近在看Tomcat和Spring的源码,在启动的时候注册了各种Listener,事件触发的时候就执行,这里就用到了设计模式中的观察者模式。

引-GUI中的事件监听

想想以前在学Java的GUI编程的时候,就用到了事件的注册监听,然后写了一个小程序试验一下:

点击按钮触发相应的事件

public class ButtonTest extends JFrame {
ButtonTest() {
JPanel panel = new JPanel();
JButton button1 = new JButton("按钮一");
JButton button2 = new JButton("按钮二"); panel.add(button1);
panel.add(button2);
this.getContentPane().add(panel);
this.setVisible(true); button1.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("你按了按钮一");
}
});
button2.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("你按了按钮二");
}
});
} public static void main(String args[]) {
new ButtonTest();
}
}

嗯,写起来确实很简单,这是封装好的,我们只需要注册事件,并实现对应的事件响应就行了。

那么这种神奇的模式是怎么实现的呢?

以下为我的分析过程。o(╯□╰)o

首先,我们来回归本质,看看到底这种模式方便在哪儿。如果不这么做的话,我们需要再每次点击按钮的代码里面把响应的内容加上,如果有一千个事件响应,我们需要把这一千个响应都写到点击按钮这个方法里面,Oh!!MyGod!太麻烦了!

如果忘掉设计模式,我们想想这种事情应该怎么做呢?

我们需要把这一千个响应管理起来,然后在事件触发的时候,把这些响应统一调用,不就行了?问题来了...

1.如何管理起来?

2.每个响应都不一样,每次写响应的时候都需要去点击事件那里加一段,改动以前的代码,此乃编程之大忌,耦合度太高

想想回答,

1.把每一个响应都通过一个响应链来管理,触发事件时,遍历这个响应链,做出响应。

2.可以定义一个接口,在响应的地方传入该接口,调用接口的方法。这样,每次需要响应的时候,实现该接口,传入具体响应的对象,这样我们就只用关心如何响应了,不用关心如何去调用响应的办法。

晕了晕了晕了……

来看看Java中的事件处理机制是如何实现的吧!

Java中的事件处理机制

来自维基百科的结构图:



图看看就行。

场景:按下开关,灯做出的响应。

1.定义事件对象

/**
* 事件对象。继承EventObject
* Created by HuangYQ on 2016/5/31.
*/
public class SwitchEvent extends EventObject { private String switchState; //表示开关的状态 public SwitchEvent(Switch source, String switchState) {
super(source);
this.switchState = switchState;
} public void setSwitchState(String switchState) {
this.switchState = switchState;
} public String getSwitchState() {
return switchState;
}
}

2.定义事件监听接口

/**
* 事件监听接口
* Created by HuangYQ on 2016/5/31.
*/
public interface SwitchListener extends EventListener { public void handleEvent(SwitchEvent switchEvent); }

我们可以在这里,再定义事件监听类,这些类具体实现了监听功能和事件处理功能。也可以用下面主程序中的匿名内部类来实现。原理一样。

3.定义事件源对象(具体的事件源,比如说,你点击一个button,那么button就是event source,要想使button对某些事件进行响应,你就需要注册特定的listener。这里指开关)

/**
* 电源开关
* 事件源对象,类似于Swing中的button
* Created by HuangYQ on 2016/5/31.
*/
public class Switch { private Vector switchListenerList = new Vector(); public void addListener(Object listener) {
switchListenerList.add(listener);
} protected void open() {
SwitchEvent switchEvent = new SwitchEvent(this, "开");
notifyListeners(switchEvent);
} protected void close() {
SwitchEvent switchEvent = new SwitchEvent(this, "关");
notifyListeners(switchEvent);
} private void notifyListeners(SwitchEvent switchEvent) {
Iterator iterator = switchListenerList.iterator();
while (iterator.hasNext()) {
SwitchListener switchListener = (SwitchListener) iterator.next();
switchListener.handleEvent(switchEvent);
}
} }

4.主程序

public class SwitchMain {

    public static void main(String[] args) {
Switch switchTest = new Switch();
switchTest.addListener(new SwitchListener() {
@Override
public void handleEvent(SwitchEvent switchEvent) {
//Do what ever you want !
System.out.println(switchEvent.getSwitchState());
}
}); //触发
switchTest.open();
switchTest.close();
}
}

运行:



仔细分析下程序,和我们之前YY的监听器其实大致一样,

个人觉得最难理解的就是事件对象SwitchEvent了。

问题

1.为什么要继承EventObject?不继承行不行

2.事件和事件源有什么联系,为什么还需要事件对象

答:

1.继承自EventObject只是为了规范,不实现当然可以。在handleEvent的时候,我们可以通过事件对象拿到我们需要的东西,这里面就有最基本的source,也就是这里的switch对象了,

2.事件和事件源关系并不大,事件对象里面包含source罢了,通过构造函数注入。

[参考]

设计模式学习----观察者模式(事件监听实现)

java事件处理机制(自定义事件)

Java设计模式——观察者模式(事件监听)的更多相关文章

  1. Java中的事件监听机制

    鼠标事件监听机制的三个方面: 1.事件源对象: 事件源对象就是能够产生动作的对象.在Java语言中所有的容器组件和元素组件都是事件监听中的事件源对象.Java中根据事件的动作来区分不同的事件源对象,动 ...

  2. java Gui编程 事件监听机制

    1.     GUI编程引言 以前的学习当中,我们都使用的是命令交互方式: 例如:在DOS命令行中通过javac java命令启动程序. 软件的交互的方式:   1. 命令交互方式    图书管理系统 ...

  3. Java界面编程—事件监听机制

    组件首先要先注册事件处理器,当用户单击组件.移动鼠标或者敲击键盘时都会产生事件(Event),一旦有时间发生,应用程序就会做出对该事件的响应,这些组件就是事件源(Event source). 接受.解 ...

  4. Java 中的事件监听机制

    看项目代码时遇到了好多事件监听机制相关的代码.现学习一下: java事件机制包含三个部分:事件.事件监听器.事件源. 1.事件:继承自java.util.EventObject类,开发人员自己定义. ...

  5. Java Spring 自定义事件监听

    ApplicationContext 事件 定义一个context的起动监听事件 import org.springframework.context.ApplicationListener; imp ...

  6. 转:java中的事件监听是怎样实现随时监听的

    http://blog.csdn.net/qq369201191/article/details/51204006

  7. SpringBoot框架(6)--事件监听

    一.场景:类与类之间的消息通信,例如创建一个对象前后做拦截,日志等等相应的事件处理. 二.事件监听步骤 (1)自定义事件继承ApplicationEvent抽象类 (2)自定义事件监听器,一般实现Ap ...

  8. springBoot高级:自动配置分析,事件监听,启动流程分析,监控,部署

    知识点梳理 课堂讲义 02-SpringBoot自动配置-@Conditional使用 Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载 ...

  9. Java事件监听机制与观察者设计模式

    一. Java事件监听机制 1. 事件监听三要素: 事件源,事件对象,事件监听器 2. 三要素之间的关系:事件源注册事件监听器后,当事件源上发生某个动作时,事件源就会调用事件监听的一个方法,并将事件对 ...

随机推荐

  1. [Python爬虫] 之十一:Selenium +phantomjs抓取活动行中会议活动信息

    一.介绍 本例子用Selenium +phantomjs爬取活动行(http://www.huodongxing.com/search?qs=数字&city=全国&pi=1)的资讯信息 ...

  2. scrapy-splash抓取动态数据例子二

    一.介绍 本例子用scrapy-splash抓取一点资讯网站给定关键字抓取咨询信息. 给定关键字:打通:融合:电视 抓取信息内如下: 1.资讯标题 2.资讯链接 3.资讯时间 4.资讯来源 二.网站信 ...

  3. 【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读

      2015-05-08 00:15 3896人阅读 评论(10) 收藏 举报 本文章已收录于:   分类: 软件开发进阶(419) 作者同类文章X Unix/Linux杂项(118) 作者同类文章X ...

  4. ElasticSearch位置搜索

    ElasticSearch位置搜索 学习了:https://blog.csdn.net/bingduanlbd/article/details/52253542 学习了:https://blog.cs ...

  5. 【翻译自mos文章】在11gR2 rac环境中,文件系统使用率紧张,而且lsof显示有非常多oraagent_oracle.l10 (deleted)

    在11gR2 rac环境中,文件系统使用率紧张.而且lsof显示有非常多oraagent_oracle.l10 (deleted) 參考原文: High Space Usage and "l ...

  6. JVM基础(1)——内存模型

    转载:http://blog.csdn.net/weitry/article/details/53264262 系列文章规划: JVM基础(1)——内存模型 JVM基础(2)——内存管理 JVM基础( ...

  7. [Swift A] - 实战-豆瓣电台总结

    最近在学Swift,也是刚刚开始.这里对自己最近所学做个简单的总结:视频和代码都在下面 http://pan.baidu.com/s/1sjHd5qX 1.String和NSString的不同 Swi ...

  8. C语言-二进制技巧

    打开位: flags = flags | MASK 要打开的位为 1 关闭位: flags = flags & ~MASK 要关闭的位为 1 转置位: flags = flags ^ MASK ...

  9. AES + RSA + Hash 实现 C-S 安全交互

    概述 AES 由于其执行速度快,易于硬件实现,破解难度大等优势,被广泛用于数据的加密. 既然是对称加密,那如何保证秘钥的安全传输?很容易想到用 RSA 加密秘钥.由于只能用私钥解密,而私钥不需要交互双 ...

  10. LinkedList的一种错误使用方法

    近期在做图像处理的时候.发现某一段代码很的慢.慢得让人无法接受.基本的代码是顺序訪问一个LinkedList的元素,效果是随着index的变大,速度越来越慢,list的元素个数在百万以上.找到原因,分 ...