最近看tomcat源码,tomcat里面的Lifecycle就是基于事件驱动模型的,感觉很犀利,而且搞的不是很懂,于是特意琢磨了老半天,上网查资料什么的,最终写出来了,为了备稿,特日志一篇……
一、首先,事件驱动模型有三个必须的因素:事件源,事件和事件监听器。
事件源:做过AWT或Swing的同志对JButton等类都不会陌生,那么,我们可以简单的理解为类似于按钮,菜单这样的实体。
事件:熟悉JButton的同志,应该对按钮的单击和双击事件比较熟悉吧,这里“单击”和“双击”就是事件,准确的说应该是事件的类型。
事件监听器:这玩意就像一个孜孜不倦的劳动者,一直在做着一件事情,那就是监听事件源的状态(当然事件监听器和事件源之间是进行了映射的,一个事件源可以有多个监听器,一个监听器也可以同时监听多个事件源),看是否有事件在事件源上发生,如果有则根据事件的类型做出相对应的处理,处理完当前事件或没有监听到事件时,再继续监听该事件源,如此循环往复下去……
二、那么弄清楚以上概念之后,我们就来看看事件驱动模型是如何工作的:
1.初始化事件源,事件,事件监听器;
2.建立事件监听器和事件源之间的联系;
3.触发事件;
4.事件监听器监听到此事件,并根据事件的类型进行相应的处理。
三、程序实现
1.事件源类,程序清单如下:
packagecom.zetsoft.lxy0307_event;
importjava.util.Date;
importjavax.swing.event.EventListenerList;
/**
*@authorluoxiaoyi
*事件源类,类似于JButton
*/
public class MySource{
public MySource(){
System.out.println("init");
}
/**
*保存注册的监听器列表.子类可以使用它保存自己的事件监听器(非MyListener监听器)列表.
*/
protected EventListenerList listenerList=new EventListenerList();
/**
*该事件源所涉及到的事件
*/
private MyEvent clickEvent=new MyEvent(this,newDate(),EventType.CLICK);
private MyEvent doubleClickEvent=new MyEvent(this,newDate(),
EventType.DOUBLE_CLICK);
/**
*添加事件监听器
*
*@paramlistener
*/
public void addMyListener(MyListener listener){
listenerList.add(MyListener.class,listener);
}
/**
*移除一个已注册的MyListener监听器.如果监听器列表中已有相同的监听器listener1、listener2,
*并且listener1==listener2,那么只移除最近注册的一个监听器。
*/
public void removeMyListener(MyListener listener){
listenerList.remove(MyListener.class,listener);
}
/**
*@return在此对象上监听的所有MyListener类型的监听器
*/
public MyListener[] getMyListeners(){
return (MyListener[])listenerList.getListeners(MyListener.class);
}
/**
*将事件源与事件和事件监听器联系起来同时执行监听器所要执行的方法
*/
protected void fireMyAction(int type){
//监听在该事件源上的所有事件监听器
Object[] myListeners=listenerList.getListenerList();
for(int i=myListeners.length-2;i>=0;i-=2){
if(myListeners[i]==MyListener.class){
MyEventmyEvent=clickEvent;
if(myEvent.getEventType()!=type)//当前是单击事件
myEvent=doubleClickEvent;
((MyListener)myListeners[i+1]).doAction(myEvent);
}
}
}
/**
*做一些事件源应该做的有意义的事,然后通知监听器.这里只是一个示例方法.
*例如:MySource如果是一个按钮,则doSomething()就可以命名为click(),当用户点击按钮时调用click()方法.
*/
public void doSomething(int type){
fireMyAction(type);//通知监听器
}
}
2.事件类,程序清单如下:
packagecom.zetsoft.lxy0307_event;
importjava.text.DateFormat;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjava.util.EventObject;
/**
*@authorluoxiaoyi
*事件类,如:ActionEvent
*/
public class MyEvent extends EventObject{
//事件类型
private int eventType;
private Date date=null;
public MyEvent(Object source,Date date,int type){
super(source);
this.date=date;
this.eventType=type;
}
public String toString(){
DateFormat df=new SimpleDateFormat("yyyy-MM-dd");
StringdateStr=null;
if(date!=null)
dateStr=df.format(date);
returnsuper.toString()+"/n"+dateStr;
}
public int getEventType(){
return eventType;
}
}
3.事件监听器,程序清单如下:
packagecom.zetsoft.lxy0307_event;
/**
*@authorluoxiaoyi
*事件监听器类,如ActionListener
*/
public interface MyListener extends java.util.EventListener{
void doAction(MyEvent e);
}
4.事件类型,程序清单如下:
packagecom.zetsoft.lxy0307_event;
/**
*@authorluoxiaoyi
*事件类型类
*/
public interface EventType{
/**
*鼠标单击事件
*/
intCLICK=1;
/**
*鼠标双击事件
*/
intDOUBLE_CLICK=2;
}
5.测试用例,程序清单如下:
packagecom.zetsoft.lxy0307_event;
/**
*@authorluoxiaoyi
*事件驱动模型测试
*/
public class MyEventTest{
public static void main(String[]args){
//构造事件源
MySource ms=new MySource();
//构造两个事件监听器
MyListener listener1=new MyListener(){
public void doAction(MyEvent e){
if(e.getEventType()==EventType.CLICK){//根据事件的类型做相应的响应
System.out.println("click event");
}else if(e.getEventType()==EventType.DOUBLE_CLICK){
System.out.println("double clickevent");
}
}
};
MyListener listener2=new MyListener(){
public void doAction(MyEvent e){
System.out.println("haha");
}
};
//事件源添加监听器
ms.addMyListener(listener1);
ms.addMyListener(listener2);
//给事件源触发事件
ms.doSomething(EventType.CLICK);
ms.doSomething(EventType.DOUBLE_CLICK);
}
}
java 事件驱动模型
最新推荐文章于 2024-08-28 09:34:31 发布