Java基础教程之事件和监听器

开发 后端
本文介绍了事件监听器的设计方法。事件监听器是经常可以遇到的一种设计模式,即:当模块的一部分A在完成后需要通知其他的软件模块B,而等待通知的模块B在事先不需要采用轮询的方式来查看另一个模块A是否通知自己。

事件监听器是经常可以遇到的一种设计模式,一般用在这样一种场景下:当模块的一部分A在完成后需要通知其他的软件模块B,而等待通知的模块B在事先不需要采用轮询的方式来查看另一个模块A是否通知自己。即,当某事件发生,则监听器立刻就知道了该事件。这种模式大量的应用在GUI设计中,比如按钮的点击,状态栏上状态的改变等等。

接口的设计

我们需要一个对事件(event)的抽象,同样需要一个对监听器(listener)的抽象。我们可以把接口抽的很简单:

这个是事件源的接口,只需要提供一个可以获取事件类型的方法即可:

package listenerdemo.framework;  
 
/**  
 * @author juntao.qiu  
 */ 
public interface EventListener {  
    /**  
     * handle the event when it raise  
     * @param event  
     */ 
    public void handleEvent(EventSource event);  
}  
   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

监听器接口,提供一个当事件发生后的处理方法即可:

package listenerdemo.framework;  
 
public interface EventSource {  
    public final int EVENT_TIMEOUT = 1;  
    public final int EVENT_OVERFLOW = 2;  
 
    /**  
     * get an integer to identify a special event  
     * @return  
     */ 
    public int getEventType();  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

实例化事件

我们举一个实现了事件源接口(EventSource)的类TimeoutEvent 来说明如何使用事件监听器模型:

package listenerdemo;  
 
import listenerdemo.framework.*;  
 
public class TimeOutEvent implements EventSource{  
    private int type;  
 
    public TimeOutEvent(){  
        this.type = EventSource.EVENT_TIMEOUT;;  
    }  
      
    public int getEventType() {  
        return this.type;  
    }  
 
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

这个事件的类型为EVENT_TIMEOUT, 当操作超时时触发该事件,我们假设这样一个场景:一个定时器T, 先设置这个定时器的时间为t,当t到时后,则触发一个超时事件,当然,事件是需要监听器来监听才有意义的。我们看看这个定时器的实现:

package listenerdemo;  
 
import listenerdemo.framework.*;  
 
/**  
 * @author juntao.qiu  
 */ 
public class Timer extends Thread{  
    private EventListener listener;  
    private int sleepSeconds;  
 
    public Timer(int seconds){  
        this.sleepSeconds = seconds;  
    }  
 
    public void setEventListener(EventListener listener){  
        this.listener = listener;  
    }  
      
    public void run(){  
        for(int i = sleepSeconds;i>0;i--){  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException ex) {  
                System.err.println(ex.getMessage());  
            }  
        }  
          
        raiseTimeoutEvent();//raise一个TimeOut事件给监听器  
    }  
 
    private void raiseTimeoutEvent(){  
        this.listener.handleEvent(new TimeOutEvent());  
    }  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

使用事件及其监听器

在类Tester的execute()方法中,我们先设置一个定时器,这个定时器初始化为3秒,设置好定时器后,程序进入一个while(true)循环中,当定时器到时后,它会发送一个timeout事件给当前线程Tester,此时我们可以设置execute中的while条件为false,退出死循环。流程很清晰了,我们来看看代码:

package listenerdemo;  
 
import listenerdemo.framework.*;  
 
/**  
 * @author juntao.qiu  
 */ 
public class EventListenerTester implements EventListener{  
    private boolean loop = true;  
 
    public void execute(){  
        Timer timer = new Timer(3);//初始化一个定时器  
        timer.setEventListener(this);//设置本类为监听器  
        timer.start();  
          
        while(loop){  
            try{  
                Thread.sleep(1000);  
                System.out.println("still in while(true) loop");  
            }catch(Exception e){  
                System.err.println(e.getMessage());  
            }  
        }  
 
        System.out.println("interupted by time out event");  
    }  
 
 
//实现了EventListener接口  
    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;  
        }  
    }  
 
    public static void main(String[] args){  
        EventListenerTester tester = new EventListenerTester();  
        tester.execute();  
    }  
 
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.

运行结果如下:
run:
still in while(true) loop
still in while(true) loop
still in while(true) loop
interupted by time out event
程序正是按照预期的方式运行了,当然,为了说明主要问题,我们的事件,对事件的处理,监听器的接口都尽可能的保持简单。如果想要完成更复杂的功能,可以参考文章中的方法自行扩充,但是大概流程文中都已经说到。

【编辑推荐】

  1. Java类中域和方法设置中的常见错误
  2. Java类体中的this和super的用法
  3. Java通过JNI调用C语言的方法
  4. Java连接MySQL中文乱码处理
  5. 浅析Java虚拟机的工作流程
责任编辑:yangsai 来源: 博客园
相关推荐

2017-07-18 10:14:23

OracleMerge into教程

2016-08-31 14:01:31

MySQL存储数据库

2010-08-09 09:47:34

Flex事件机制

2020-12-15 10:46:29

事件监听器Spring Boot

2009-07-17 09:55:02

事件监听器SWT和SwingAWT

2012-02-03 13:27:16

2010-08-09 11:06:01

Flex事件机制

2021-07-08 07:52:49

容器监听器Event

2021-07-16 07:21:45

C++可调用对象std::functi

2009-07-24 09:20:15

数组实例

2011-04-25 09:22:44

C#事件

2023-11-01 07:55:03

事件监听器传递数据

2011-03-21 16:21:49

Oracle监听口令监听器

2021-02-06 07:49:48

C语言编程开发技术

2010-01-13 09:49:09

注释监听器Listener

2011-04-15 09:20:56

ASP.NET MVC

2009-07-08 17:39:23

Servlet监听器

2009-09-27 17:46:22

Hibernate监听

2011-04-26 08:56:31

C#

2011-07-21 10:17:53

java
点赞
收藏

51CTO技术栈公众号