监听器模式有三个要素——事件源、事件对象、监听器。

事件源:顾名思义,事件发生的源头,比如点击的按钮,属于被监听的对象;

事件对象:这个经常和事件源混淆,它经常被用来包装事件源,切记,它毕竟是个事件,比如点击事件,和事件源的区别自己感受,木有栗子;

监听器:这个是监听器模式的核心,定义事件发生后的动作,通常事件对象作为监听器中定义的函数入参。

下面举个简单的栗子:

故事背景是,小明是个不讲卫生的孩子,他妈妈很担心他的健康,规定必须饭前洗手。

定义一个熊孩子。熊孩子就是被监听的对象,是事件源,一切事件都是事件源发出,这似乎是句废话。

public class Child {
private String name;
private RemindListener remindListener; public Child(String name){
this.name = name;
}
public void eat() {
if(null!=remindListener){
remindListener.remind(new RemindWashingHandsEvent(this));
}
System.out.println("Child eat...");
} public void addListener(RemindListener listener){
remindListener = listener;
}
}

接下来是看看事件对象,事件对象正如上面所述,包装了事件源。我们在这里定义一个饭前洗手事件。

public class RemindWashingHandsEvent {
private Child child; public RemindWashingHandsEvent(Child child){
this.child = child;
}
}

事件对象定义了事件的属性、状态。

紧接着是定义事件发生后,监听器的动作,在这里是提醒洗手。

public class RemindListener {
public void remind(RemindWashingHandsEvent remindWashingHandsEvent){
System.out.println("listen to mom, washing hands before eating...");
}
}

注意,监听器主要封装了动作,仅此而已。

以上代码,只是为了说明监听器模式原理,代码通俗,不太优雅。

下面继承或实现java标准库,又随手写了一对代码,夜深了,有时间再解释。

public class Kid{
private String name;
private List<Listener> liteners; public Kid(String name) {
this.name = name;
this.liteners = Lists.newArrayList();
} public void eat(){ for(Listener listener:liteners){
if(listener instanceof WashingHandsListener){
WashingHandsListener washingHandsListener = (WashingHandsListener) listener;
washingHandsListener.fireAfterEventInvoked(new WashingHandsEvent(this,"洗手"));
}
}
System.out.println("吃饭...");
} public void addListener(Listener listener){
liteners.add(listener);
} }

  

public class Event extends EventObject {
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public Event(Object source) {
super(source);
}
}

  

public class WashingHandsEvent extends Event{
private String eventName;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public WashingHandsEvent(Object source,String eventName) {
super(source);
this.eventName = eventName;
} public String getEventName() {
return eventName;
} public void setEventName(String eventName) {
this.eventName = eventName;
}
}

  

public interface Listener extends java.util.EventListener{
public void fireAfterEventInvoked(Event event);
}

  

public class WashingHandsListener implements Listener{
@Override
public void fireAfterEventInvoked(Event event) {
WashingHandsEvent washingHandsEvent = (WashingHandsEvent) event;
System.out.println("饭前准备"+ washingHandsEvent.getEventName());
}
}

  

public class Test {
public static void main(String[] args) {
Kid xiaoming = new Kid("xiaoming");
xiaoming.addListener(new WashingHandsListener());
xiaoming.eat();
}
}

输出结果:

Java设计模式-监听器模式的更多相关文章

  1. Java设计模式——组合模式

    JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...

  2. java设计模式--单列模式

    java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...

  3. 3.java设计模式-建造者模式

    Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...

  4. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  5. Java设计模式——外观模式

    JAVA 设计模式 外观模式 用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构

  6. 【设计模式】Java设计模式 -工厂模式

    [设计模式]Java设计模式 -工厂模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目 ...

  7. 【设计模式】Java设计模式 - 原型模式

    [设计模式]Java设计模式 - 原型模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起 ...

  8. 【设计模式】Java设计模式 - 桥接模式

    [设计模式]Java设计模式 - 桥接模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起 ...

  9. 【设计模式】Java设计模式 - 组合模式

    Java设计模式 - 组合模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

随机推荐

  1. linux下svn服务器的搭建

    网上的教程实在是太恶心了,不是太老,就是有问题,刚参考的一篇文章也有问题.自己记录下来,以后用就方便了,现在一边重新安装一遍,一边记录.笔者亲测,今天是5月29号深夜. linux用的是centos6 ...

  2. Javascript设计模式理论与实战:工厂方法模式

    本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用.在之前的<Javascript设计模式理论与实战:简单工厂模 ...

  3. 执行计划--WHERE条件的先后顺序对执行计划的影响

    在编写SQL时,会建议将选择性高(过滤数据多)的条件放到WHERE条件的前面,这是为了让查询优化器优先考虑这些条件,减少生成最优(或相对最优)的执行计划的时间,但最终的执行计划生成过滤顺序还是决定这些 ...

  4. WPF 分享一种设置程序保存配置文件的方法

    最近需要做一个配置程序,主要给其他程序做相关配置的小工具. 配置项蛮多的,一般我们都是将各个配置项写到配置文件的节点中,比如App.config文件或者自定义的xml文件. 因为我用的是wpf,MVV ...

  5. netcat 工具传输文件

    因为电脑本地是 windows,多台机器间以 windows 为中介传输文件极度不爽.window 下的 MobaXterm 工具不能使用 sz 和 rz 命令, 而 SecureCRT 工具使用体验 ...

  6. AcDbTable表格实体的简单例子

    例子是创建一个含有表格实体的块定义 效果如下(手动插入的块) 源代码如下,简单示意,采用了我不是很熟悉的智能指针创建实体对象,代码仅供参考 AcDbObjectPointer<AcDbTable ...

  7. C语言中宏定义与C++中的内联函数

    一,宏定义:在预处理的时候把宏定义的内容替换到代码中,正常编译. 1,无参数宏定义和有参数宏定义 (1)宏定义不能加分号,比如:#define  PI 3.24;错的,#define  PI 3.24 ...

  8. aspx代码审计-1

    今天和大家分享一下aspx网站的代码审计,漏洞类型就是SQL注入和cookie欺骗. 本文作者:i春秋签约作家——非主流 今天看的cms名字叫做:XX星员工请假系统 我们首先看一下网站的目录结构: 其 ...

  9. Elasticsearch 5 Ik+pinyin分词配置详解

    版权声明:本文为博主原创文章,地址:http://blog.csdn.net/napoay,转载请留言. 一.拼音分词的应用 拼音分词在日常生活中其实很常见,也许你每天都在用.打开淘宝看一看吧,输入拼 ...

  10. Vim 中的持久撤消

    Vim中的持久撤消 阅读文本大约需要俩分钟. 在 Vim 中像其他文本编辑器一样,你可以在当前会话中执行 "撤销/重做" .当一旦会话关闭,则你需要重新打开一个新文章,运行撤销将不 ...