监听器模式:
事件监听器是经常可以遇到的一种设计模式,一般用在这样一种场景下:
当模块的一部分A在完成后需要通知其他的软件模块B,而等待通知的模
块B在事先不需要采用轮询的方式来查看另一个模块A是否通知自己。即,
当某事件发生,则监听器立刻就知道了该事件。
接口的设计:
我们需要一个对事件(event)的抽象,同样需要一个对监听器(listener)的抽象。
EventSource.java是事件源的接口,只需要提供一个可以获取事件类型的方法即可
EventListener.java监听器接口,提供一个当事件发生后的处理方法即可
事件监听器是经常可以遇到的一种设计模式,一般用在这样一种场景下:
当模块的一部分A在完成后需要通知其他的软件模块B,而等待通知的模
块B在事先不需要采用轮询的方式来查看另一个模块A是否通知自己。即,
当某事件发生,则监听器立刻就知道了该事件。
接口的设计:
我们需要一个对事件(event)的抽象,同样需要一个对监听器(listener)的抽象。
EventSource.java是事件源的接口,只需要提供一个可以获取事件类型的方法即可
EventListener.java监听器接口,提供一个当事件发生后的处理方法即可
项目的目录结构:
EvenListener.java文件内容:
package com.listener.framework;
/**
* 事件监听器接口.
*/
public interface EventListener {
/**
* 根据事件源实例的不同状态,来确定相应的响应.
* @param event 事件源实例.
*/
void handleEvent(EventSource event);
}
EventSource.java文件内容:
package com.listener.framework;
/**
* 事件源接口.
*/
public interface EventSource {
/**
* 事件类型1.
*/
public final int EVENT_TIMEOUT = 1;
/**
* 事件类型2.
*/
public final int EVENT_OVERFLOW = 2;
/**
* 获取事件类型.
* @return 事件类型
*/
int getEventType();
}
Timer.java文件内容:
package com.listener.framework.impl;
import com.listener.framework.EventListener;
/**
* 定时器.
*/
public class Timer extends Thread {
/**
* 监听器.
*/
private EventListener listener;
/**
* 定时毫秒数.
*/
private int sleepSeconds;
/**
* 无参构造方法.
*/
public Timer(){
}
/**
* 实例化定时seconds毫秒的定时器.
* @param seconds 毫秒数.
*/
public Timer(int seconds){
this.sleepSeconds = seconds;
}
/**
* 设置监听器.
* @param listener 监听器.
*/
public void setEventListener(EventListener listener){
this.listener = listener;
}
@Override
public void run() {
for(int i = sleepSeconds; i > 0; i--){
try {
System.out.println("Timer.run()");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.err.println(e.getMessage());
}
}
//当sleepSeconds过后,事件源向所注册的监听器发送事件对象
raiseTimeoutEvent();
}
/**
* 唤醒timeout事件.
*/
private void raiseTimeoutEvent(){
//raise一个TimeOut事件给监听器
this.listener.handleEvent(new TimeOutEvent());
}
}
TimeOutEvent.java文件内容:
package com.listener.framework.impl;
import com.listener.framework.EventSource;
/**
* 超时事件.
*/
public class TimeOutEvent implements EventSource {
/**
* 事件类型.
*/
private int type;
/**
* 实例化超时事件.
*/
public TimeOutEvent(){
this.type = EventSource.EVENT_TIMEOUT;
}
/**
* 获取事件类型.
*/
public int getEventType() {
return this.type;
}
}
TimeListenerTester.java文件内容:
package com.listener.framework.impl;
import com.listener.framework.EventListener;
import com.listener.framework.EventSource;
/**
* 我们假设这样一个场景:一个定时器T, 先设置这个定时器的时间为t,当t到时后,则触发一个超时事件
* 在类EventListenerTester的execute()方法中,我们先设置一个定时器,这个定时器初始化为3秒,设置好定时器后,
* 程序进入一个while(true)循环中,当定时器到时后,它会发送一个timeout事件给当前线程Tester,
* 此时我们可以设置execute中的while条件为false,退出死循环。
*/
public class EventListenerTester implements EventListener {
private boolean loop = true;
public void execute() {
// 创建定时器timer
Timer timer = new Timer(3);
// 为定时器注册监听器this
timer.setEventListener(this);
//定时器启动,当3秒之后,定时器向监听器发送事件
timer.start();
//监听器会调用handleEvent(EventSource event)方法来根据定时器所发送过来的事件对象做出相应的响应
try {
while (loop) {
Thread.sleep(1000);
System.out.println("still in while(true) loop");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("interupted by time out event");
}
// 监听器根据事件对象信息中传来的信息来确定对事件的响应
@Override
public void handleEvent(EventSource event) {
int eType = event.getEventType();
switch (eType) {
case EventSource.EVENT_TIMEOUT:
this.loop = false;
break;
case EventSource.EVENT_OVERFLOW:
break;
default:
this.loop = true;
break;
}
}
/**
* 测试.
* @param args
*/
public static void main(String[] args) {
EventListenerTester tester = new EventListenerTester();
tester.execute();
}
}