[關鍵字]:java,design pattern,設計模式,《Java與模式》學習,閻宏,Ph.D,Factory,觀察者模式,observer,event,java自定義事件,java事件機制,事件模型,事件監聽,訂閱發布,事件消息
[環境]:StarUML5.0 + JDK6
[作者]:天堂露珠 (wintys@gmail.com) http://www.tkk7.com/wintys
[正文]:
MyEventTest.java:
package wintys.event;
import javax.swing.event.EventListenerList;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* Java的事件機制/自定義事件.
運行結果:
do something interesting in source here.
listener detects [event]:wintys.event.MyEvent[source=wintys.event.MySource@18158
59] [occur at]:2009-10-11 16:27:49
listener detects [event]:wintys.event.MyEvent[source=wintys.event.MySource@18158
59] [occur at]:2009-10-11 16:27:49
* @version 2009-10-11
* @author 天堂露珠 (wintys@gmail.com)
* @see http://www.tkk7.com/wintys
*/
class MyEventTest{
public static void main(String[] args){
MySource source = new MySource();
MyListener myListener = new MyListener(){
public void doMyAction(MyEvent e){
System.out.println("listener detects " + e);
}
};
source.addMyListener(myListener);
source.addMyListener(myListener);
source.addMyListener(myListener);
source.removeMyListener(myListener);
source.doSomething();
}
}
/**
* 自定義的事件.
* @version 2009-10-11
* @author 天堂露珠(wintys@gmail.com)
* @see http://www.tkk7.com/wintys
*/
class MyEvent extends java.util.EventObject{
private Date date;//記錄事件發生的時間
public MyEvent(Object source , Date date){
super(source);
this.date = date;
}
public String toString(){
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dt = df.format(date);
return "[event]:" + super.toString() + " [occur at]:" + dt;
}
}
/**
* 自定義事件監聽器接口.
* @version 2009-10-11
* @author 天堂露珠(wintys@gmail.com)
* @see http://www.tkk7.com/wintys
*/
interface MyListener extends java.util.EventListener{
void doMyAction(MyEvent e);
}
/**
* 自定義事件源.
* @version 2009-10-11
* @author 天堂露珠(wintys@gmail.com)
* @see http://www.tkk7.com/wintys
*/
class MySource{
/**
* 保存注冊的監聽器列表.
* 子類可以使用它保存自己的事件監聽器(非MyListener監聽器)列表.
*/
protected EventListenerList listenerList = new EventListenerList();
private MyEvent myEvent = null;//fireDoMyAction()使用此變量
/**
* 沒有做任何事
*/
public MySource(){
}
/**
* 添加一個MyListener監聽器
*/
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);
}
//Winty:Copy directly from javax.swing.event.EventListenerList
/*Notify all listeners that have registered interest for
notification on this event type. The event instance
is lazily created using the parameters passed into
the fire method.
*/
protected void fireDoMyAction() {
// getListenerList() Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MyListener.class) {
// Lazily create the event:
if (myEvent == null)
myEvent = new MyEvent(this , new Date());
((MyListener)listeners[i+1]).doMyAction(myEvent);
}
}
}
/**
* 做一些事件源應該做的有意義的事,然后通知監聽器.
* 這里只是一個示例方法.
* 例如:MySource如果是一個按鈕,則doSomething()就可以命名為click(),
* 當用戶點擊按鈕時調用click()方法.
*/
public void doSomething() {
System.out.println("do something interesting here.");
fireDoMyAction();//通知監聽器
}
}
EventListenerList是特別需要說明的,它內部使用一個Object數組存放監聽器。但是它并不是直接存放,而是先存監聽器的class類型,然后再存監聽器本身。即存放(MyListener.class
,
myListener)。一個Object數組可以存放多種類型的Listener,如果還有一種監聽器AnotherListener,那么(AnotherListener.class
,
anotherListener)也可以存放。無論增刪都是兩個對象一同被添加或刪除。上述代碼中的listenerList.add(MyListener.class
, listener)或listenerList.remove(MyListener.class ,
listener),以及fireDoMyAction()中的"i-=2",就是這樣操作的。
[參考資料]:
[1] 《java 自定義事件》 : http://blog.csdn.net/qking93415981/archive/2007/08/29/1763757.aspx
[2] 《Use EventListenerList to store event listener list》 : http://www.java2s.com/Code/Java/Swing-JFC/UseEventListenerListtostoreeventlistenerlist.htm
[3] 《創建一個自定義事件》 : http://www.java2s.com/CN/Code/Java/Event/CreatingaCustomEvent.htm
[4] 《java 自定義事件的觸發及監聽》 : http://zhidao.baidu.com/question/50126506.html
[5] 《關于觀察者模式的問題》 : http://www.javaeye.com/topic/182643
[6] JDK1.6源代碼
[7] 《Java與模式》 : 閻宏
[附件]:
EventListener.java
EventListenerList.java
EventObject.java
MyEventTest.java
原創作品,轉載請注明出處。
作者:Winty (wintys@gmail.com)
博客:http://www.tkk7.com/wintys
posted on 2009-10-11 20:32
天堂露珠 閱讀(3868)
評論(2) 編輯 收藏 所屬分類:
Pattern