隨筆 - 117  文章 - 72  trackbacks - 0

          聲明:原創(chuàng)作品(標(biāo)有[原]字樣)轉(zhuǎn)載時(shí)請(qǐng)注明出處,謝謝。

          常用鏈接

          常用設(shè)置
          常用軟件
          常用命令
           

          訂閱

          訂閱

          留言簿(7)

          隨筆分類(130)

          隨筆檔案(123)

          搜索

          •  

          積分與排名

          • 積分 - 156402
          • 排名 - 390

          最新評(píng)論

          [關(guān)鍵字]:java,design pattern,設(shè)計(jì)模式,《Java與模式》學(xué)習(xí),閻宏,Ph.D,Factory,觀察者模式,observer,event,java自定義事件,java事件機(jī)制,事件模型,事件監(jiān)聽(tīng),訂閱發(fā)布,事件消息
          [環(huán)境]:StarUML5.0 + JDK6
          [作者]:天堂露珠 (wintys@gmail.comhttp://www.aygfsteel.com/wintys
          [正文]:

          java_event     MyEventTest.java:

          package wintys.event;
          import javax.swing.event.EventListenerList;
          import java.util.Date;
          import java.text.DateFormat;
          import java.text.SimpleDateFormat;

          /**
          * Java的事件機(jī)制/自定義事件.

          運(yùn)行結(jié)果:
          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.aygfsteel.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.aygfsteel.com/wintys
          */
          class MyEvent extends java.util.EventObject{
              private Date date;//記錄事件發(fā)生的時(shí)間

              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;
              }
          }

          /**
          * 自定義事件監(jiān)聽(tīng)器接口.
          * @version 2009-10-11
          * @author 天堂露珠(wintys@gmail.com)
          * @see http://www.aygfsteel.com/wintys
          */
          interface MyListener extends java.util.EventListener{
              void doMyAction(MyEvent e);
          }

          /**
          * 自定義事件源.
          * @version 2009-10-11
          * @author 天堂露珠(wintys@gmail.com)
          * @see http://www.aygfsteel.com/wintys
          */
          class MySource{
              /**
               * 保存注冊(cè)的監(jiān)聽(tīng)器列表.
               * 子類可以使用它保存自己的事件監(jiān)聽(tīng)器(非MyListener監(jiān)聽(tīng)器)列表.
               */

              protected EventListenerList listenerList = new EventListenerList();
              private MyEvent myEvent = null;//fireDoMyAction()使用此變量

              /**
               * 沒(méi)有做任何事
               */
              public MySource(){
              }
              /**
               * 添加一個(gè)MyListener監(jiān)聽(tīng)器
               */
              public void addMyListener(MyListener listener){
                  listenerList.add(MyListener.class , listener);
              }

              /**
               * 移除一個(gè)已注冊(cè)的MyListener監(jiān)聽(tīng)器.
               * 如果監(jiān)聽(tīng)器列表中已有相同的監(jiān)聽(tīng)器listener1、listener2,
               * 并且listener1==listener2,
               * 那么只移除最近注冊(cè)的一個(gè)監(jiān)聽(tīng)器。
               */
              public void removeMyListener(MyListener listener){
                  listenerList.remove(MyListener.class , listener);
              }

              /**
               * @return 在此對(duì)象上監(jiān)聽(tīng)的所有MyListener類型的監(jiān)聽(tīng)器
               */
              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);
                      }
                  }
              }

              /**
               * 做一些事件源應(yīng)該做的有意義的事,然后通知監(jiān)聽(tīng)器.
               * 這里只是一個(gè)示例方法.
               * 例如:MySource如果是一個(gè)按鈕,則doSomething()就可以命名為click(),
               * 當(dāng)用戶點(diǎn)擊按鈕時(shí)調(diào)用click()方法.
               */
              public void doSomething() {
                  System.out.println("do something interesting here.");

                  fireDoMyAction();//通知監(jiān)聽(tīng)器
              }
          }

             EventListenerList是特別需要說(shuō)明的,它內(nèi)部使用一個(gè)Object數(shù)組存放監(jiān)聽(tīng)器。但是它并不是直接存放,而是先存監(jiān)聽(tīng)器的class類型,然后再存監(jiān)聽(tīng)器本身。即存放(MyListener.class , myListener)。一個(gè)Object數(shù)組可以存放多種類型的Listener,如果還有一種監(jiān)聽(tīng)器AnotherListener,那么(AnotherListener.class , anotherListener)也可以存放。無(wú)論增刪都是兩個(gè)對(duì)象一同被添加或刪除。上述代碼中的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] 《創(chuàng)建一個(gè)自定義事件》 : http://www.java2s.com/CN/Code/Java/Event/CreatingaCustomEvent.htm

            [4] 《java 自定義事件的觸發(fā)及監(jiān)聽(tīng)》 : http://zhidao.baidu.com/question/50126506.html

            [5] 《關(guān)于觀察者模式的問(wèn)題》 : http://www.javaeye.com/topic/182643

            [6]  JDK1.6源代碼

            [7] 《Java與模式》 : 閻宏

           

          [附件]:

          event_MyEventTest.zip :

          EventListener.java
          EventListenerList.java
          EventObject.java
          MyEventTest.java

          原創(chuàng)作品,轉(zhuǎn)載請(qǐng)注明出處。
          作者:Winty (wintys@gmail.com)
          博客:http://www.aygfsteel.com/wintys
          posted on 2009-10-11 20:32 天堂露珠 閱讀(3880) 評(píng)論(2)  編輯  收藏 所屬分類: Pattern

          FeedBack:
          # re: [原]觀察者模式-Java自定義事件 2009-10-12 12:04 Scorpio Zhen
          做個(gè)標(biāo)記  回復(fù)  更多評(píng)論
            
          # re: [原]觀察者模式-Java自定義事件 2009-10-12 16:58 document
          good...  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 峨边| 佛坪县| 昆山市| 留坝县| 通城县| 常州市| 马尔康县| 恩施市| 重庆市| 建湖县| 米泉市| 郸城县| 尼玛县| 翁牛特旗| 安徽省| 怀远县| 阜南县| 调兵山市| 巫山县| 孟津县| 浪卡子县| 府谷县| 岳池县| 九龙坡区| 错那县| 莱州市| 乌什县| 尖扎县| 赤水市| 溧水县| 永平县| 长垣县| 阿克苏市| 丹阳市| 巴塘县| 达孜县| 涿鹿县| 婺源县| 贵德县| 临洮县| 庆云县|