文档章节

监听者模式

徐航
 徐航
发布于 2015/02/27 12:14
字数 948
阅读 183
收藏 4
点赞 0
评论 0

监听者模式是观察者模式实现的一种,也属于Publish/Subscribe模式,被监听者触发某一事件后向监听者发送通知。在java中最常用的就是在编写GUI程序时,控件的事件监听了。

通常在编写java的GUI程序时,需要在控件上注册一个监听器,这个监听器需要开发人员自己编写,当控件被监听的事件触发后,监听器也会做出响应的反应。

<!-- lang: java -->
Frame frame = new Frame("java");
frame.setBounds(400, 300, 300, 200);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter(){
	public void windowClosing(WindowEvent e) {
		Frame f = (Frame) e.getSource();
		f.dispose();
	}
});

控件的关闭按钮默认并不会将窗口关闭,这需要开发人员编写关闭窗口的代码,WindowAdapter是实现了WindowListener接口所有方法的一个适配器类,但是所有方法都没有具体的代码,这样开发人员就可以只针对特定的事件进行监听,其他的事件即使触发了也不会做任何反应。

在实现监听者模式之前需要清楚,监听者模式设计的三个对象:事件源(Source)监听器(Listener)事件(Event)

事件源:发生事件的主体,上面的例子中是Frame控件,当事件源上发生操作时,它会调用时间监听器的一个方法,并将事件对象作为参数传递过去。

监听器:通常是一个接口,事件源被触发事件后作出响应,具体响应由开发人员编写实现类。

事件:发生在事件源上,持有事件源的引用。

接下来编写一个用户操作的监听器案例:

  1. 事件源是User,user的更新删除操作时需要被监听的事件。

  2. 监听器是UserListener,监听User对象,事件触发后的具体操作由开发人员编写。

  3. 事件是UserEvent,持有对事件源User对象的引用。

事件源:User.java

<!-- lang: java -->
public class User {
public String name;

public User(String name) {
	this.name = name;
}

public void updateUser() {
	if (userListener != null) {
		userListener.updateUser(new UserEvent(this));
	}
	System.out.println("更新用户" + this.name);
}

public void deleteUser() {
	if (userListener != null) {
		userListener.deleteUser(new UserEvent(this));
	}
	System.out.println("删除用户" + this.name);
}

public IUserListener userListener;

public void addListener(IUserListener userListener) {
	this.userListener = userListener;
}
}

监听器接口:IUserListener.java

<!-- lang: java -->
public interface IUserListener {
public void updateUser(UserEvent e);
public void deleteUser(UserEvent e);
}

事件:UserEvent.java

<!-- lang: java -->
public class UserEvent {
private Object source;

public UserEvent(Object source) {
	this.source = source;
}

public Object getSource() {
	return source;
}

public void setSource(Object source) {
	this.source = source;
}

}

实现一个监听器类:UserListener

<!-- lang: java -->
public class UserListener implements IUserListener{
@Override
public void updateUser(UserEvent e) {
	User user = (User) e.getSource();
	System.out.println("监听到用户" + user.name + "的更新操作。。。");
}
public void deleteUser(UserEvent e) {
    //...
}
}

测试:App.java

<!-- lang: java -->
public class App {
public static void main(String[] args) {
	User user = new User("张三");
	//user.addListener(new UserListener());//也可以通过匿名内部类的方式实现监听器类
	user.addListener(new IUserListener(){
		public void updateUser(UserEvent e) {
		    User user = (User) e.getSource();
	        System.out.println("监听到用户" + user.name + "的更新操作。。。");
		}
		public void deleteUser(UserEvent e) {
			User user = (User) e.getSource();
			System.out.println("监听到用户" + user.name + "的删除操作。。。");
		}
		
	});
	user.deleteUser();
}
}

运行结果:

监听到用户张三的更新操作。。。 更新用户张三 监听到用户张三的删除操作。。。 删除用户张三

不添加监听器的运行结果:

更新用户张三 删除用户张三


##JDK中awt包下的图形控件的监听事件源码

EventObject

java.util.EventObject

<!-- lang: java -->
public class EventObject implements java.io.Serializable {
    private static final long serialVersionUID = 5516075349620653480L;
    protected transient Object  source;
    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");

        this.source = source;
    }
    public Object getSource() {
        return source;
    }
    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}

<br/> ![Window][2]

java.awt.Window

<!-- lang: java -->
public class Window extends Container implements Accessible {
    ...
    ...
    protected void processWindowEvent(WindowEvent e) {
        WindowListener listener = windowListener;
        if (listener != null) {
            switch(e.getID()) {
                case WindowEvent.WINDOW_OPENED:
                    listener.windowOpened(e);
                    break;
                case WindowEvent.WINDOW_CLOSING:
                    listener.windowClosing(e);
                    break;
                case WindowEvent.WINDOW_CLOSED:
                    listener.windowClosed(e);
                    break;
                case WindowEvent.WINDOW_ICONIFIED:
                    listener.windowIconified(e);
                    break;
                case WindowEvent.WINDOW_DEICONIFIED:
                    listener.windowDeiconified(e);
                    break;
                case WindowEvent.WINDOW_ACTIVATED:
                    listener.windowActivated(e);
                    break;
                case WindowEvent.WINDOW_DEACTIVATED:
                    listener.windowDeactivated(e);
                    break;
                default:
                    break;
            }
        }
    }
    ...
    ...
}

<br/> **java.awt.event.WindowListener**

<!-- lang: java -->
public interface WindowListener extends EventListener {
    public void windowOpened(WindowEvent e);
    public void windowClosing(WindowEvent e);
    public void windowClosed(WindowEvent e);
    public void windowIconified(WindowEvent e);
    public void windowDeiconified(WindowEvent e);
    public void windowActivated(WindowEvent e);
    public void windowDeactivated(WindowEvent e);
}

© 著作权归作者所有

共有 人打赏支持
徐航
粉丝 15
博文 28
码字总数 19400
作品 0
武汉
程序员
从消息机制谈到观察者模式

从简单的例子开始 同样,我们还是先看一个简单例子:创建一个窗口实现加法的计算功能。其效果如下: 图1: 加法计算 Calculator.java: import javax.swing.;import javax.swing.border.Bevel...

Sheamus ⋅ 2016/03/14 ⋅ 0

Redis实现消息队列

基于Redis消息队列-实现短信服务化 1.Redis实现消息队列原理 常用的消息队列有RabbitMQ,ActiveMQ,个人觉得这种消息队列太大太重,本文介绍下基于Redis的轻量级消息队列服务。 一般来说,消息...

voole ⋅ 2016/08/07 ⋅ 2

Android 框架学习3:从 EventBus 中学到的精华

关联文章: EventBus 3.0 的特点与如何使用 源码分析 EventBus 3.0 如何实现事件总线 学习的目的是为了超越,经过前面对 EventBus 3.0 的学习,我们已经对它相当熟悉了,现在来总结下,从这个...

u011240877 ⋅ 2017/07/06 ⋅ 0

Java for Web学习笔记(八七):消息和集群(2)应用内的publish和subscribe

学习内容 Spring框架很强大,已经自带app内部的消息发布订阅了。我们甚至不需要在配置文件(代码)中加入任何内容。 我们将学习如何在一个spring应用内进行消息的发布和订阅 定义事件 事件需...

flowingflying ⋅ 2017/11/10 ⋅ 0

NSNotificationCenter 与设计模式 (Observer)

龙生九子,设计模式中的“抽象” 在开发中,我们面临各种模块的开发。为了降低模块间的偶合性,我们往往先把模块间的接口抽象出来,以应对高速变化的需求与业务。 模块多了,接口也就多了; ...

Jeans ⋅ 2012/07/21 ⋅ 0

面试官: 你为什么使用前端框架?

面试官系列(5): 你为什么使用前端框架? 往期 面试官系列(1): 如何实现深克隆 面试官系列(2): Event Bus的实现 面试官系列(3): 前端路由的实现 面试官系列(4): 基于Proxy 数据劫持的双向绑定优...

寻找海蓝96 ⋅ 06/06 ⋅ 0

编程思想之消息机制

1.编程思想之消息机制 什么是消息? 何为消息?消息就是带有某种信息的信号,如你用鼠标点击一个窗口会产生鼠标的消息,键盘输入字符会产生键盘的消息,一个窗口大小的改变也会产生消息。 消...

火力全開 ⋅ 2016/10/09 ⋅ 0

JS中的异步操作

JS中异步编程的方法有: 回调函数 事件监听 发布/订阅 promise generator(ES6) async/await(ES7) 回调函数 回调是异步编程中最基础的方法。举例一个简单的回调:在f1执行完之后再执行f2 异...

RichardBillion ⋅ 2017/04/10 ⋅ 0

KPortTran JSP端口转发工具

由于windows和linux的差别以及运行语言环境的限制导致端口转发经常出现问题。于是自己写了个简单的JSP的端口转发脚本。仿造LCX的功能,具有正向、反向、监听三种模式。对于目前数量众多的JAV...

滔哥 ⋅ 2013/12/25 ⋅ 0

iOS之观察者模式

观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。 在iOS中典型的观察者模式实现方式为NSNotificat...

iOS俱哥 ⋅ 2016/11/20 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Confluence 6 从其他备份中恢复数据

一般来说,Confluence 数据库可以从 Administration Console 或者 Confluence Setup Wizard 中进行恢复。 如果你在恢复压缩的 XML 备份的时候遇到了问题,你还是可以对整个站点进行恢复的,如...

honeymose ⋅ 昨天 ⋅ 0

myeclipse10 快速搭建spring boot开发环境(入门)

1.创建一个maven的web项目 注意上面标红的部分记得选上 2.创建的maven目录结构,有缺失的目录可以自己建立目录补充 补充后 这时候一个maven的web项目创建完成 3.配置pom.xml配置文件 <proje...

小海bug ⋅ 昨天 ⋅ 0

nginx.conf

=========================================================================== nginx.conf =========================================================================== user nobody; #......

A__17 ⋅ 昨天 ⋅ 0

645. Set Mismatch - LeetCode

Question 645. Set Mismatch Solution 思路: 遍历每个数字,然后将其应该出现的位置上的数字变为其相反数,这样如果我们再变为其相反数之前已经成负数了,说明该数字是重复数,将其将入结果r...

yysue ⋅ 昨天 ⋅ 0

Python这么强?红包杀手、消息撤回也可以无视,手机App辅助!

论述 标题也许有点不好理解,其实就是一款利用Python实现的可以监控微信APP内的红包与消息撤回的助手。不得不说,这确实是一款大家钟意的神器。 消息撤回是一件很让人恶心的事,毕竟人都是有...

Python燕大侠 ⋅ 昨天 ⋅ 0

压缩打包介绍、gzip压缩工具、bzip2压缩工具、xz压缩工具

压缩打包介绍 压缩的好处不仅能节省磁盘空间而且在传输的时候节省传输时间和网络带宽 windows系统下文件带有 .rar .zip .7z 后缀的就是压缩文件 linux系统下则是 .zip, .gz, .bz2, .xz, ...

黄昏残影 ⋅ 昨天 ⋅ 0

观察者模式

1.利用java原生类进行操作 package observer;import java.util.Observable;import java.util.Observer;/** * @author shadow * @Date 2016年8月12日下午7:29:31 * @Fun 观察目标 **/......

Cobbage ⋅ 昨天 ⋅ 0

Ubuntu打印服务器配置

参考:https://blog.csdn.net/gsls200808/article/details/50950586 https://blog.csdn.net/jiay2/article/details/80252369 https://wiki.gentoo.org/wiki/HPLIP 由于媳妇儿要大量打印资料,......

大熊猫 ⋅ 昨天 ⋅ 0

面试的角度诠释Java工程师(二)

原文出处: locality 续言: 相信每一位简书的作者,都会有我这样的思考:怎么写好一篇文章?或者怎么写好一篇技术类的文章?我就先说说我的感悟吧,写文章其实和写程序是一样的。为什么我会...

颖伙虫 ⋅ 昨天 ⋅ 0

github中SSH的Key

https://help.github.com/articles/connecting-to-github-with-ssh/ https://help.github.com/articles/testing-your-ssh-connection/ https://help.github.com/articles/adding-a-new-ssh-k......

whoisliang ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部