`

[原]观察者模式-Java自定义事件

阅读更多

[关键字]:java,design pattern,设计模式,《Java与模式》学习,阎宏,Ph.D,Factory,观察者模式,observer,event,java自定义事件,java事件机制,事件模型,事件监听,订阅发布,事件消息
[环境]:StarUML5.0 + JDK6
[作者]:天堂露珠 (wintys@gmail.comhttp://www.blogjava.net/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的事件机制/自定义事件.

运行结果:
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.blogjava.net/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.blogjava.net/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.blogjava.net/wintys
*/
interface MyListener extends java.util.EventListener{
    void doMyAction(MyEvent e);
}

/**
* 自定义事件源.
* @version 2009-10-11
* @author 天堂露珠(wintys@gmail.com)
* @see http://www.blogjava.net/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.iteye.com/topic/182643

  [6]  JDK1.6源代码

  [7] 《Java与模式》 : 阎宏

 

[附件]:

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

原创作品,转载请注明出处。
作者:Winty (wintys@gmail.com)
博客:http://www.blogjava.net/wintys
分享到:
评论

相关推荐

    java实现观察者模式-自定义的观察者接口和主题类

    观察者模式都能帮助实现对象之间的松耦合、依赖关系的解耦,并提供一种动态的消息通知机制

    design-pattern-java.pdf

    撤销功能的实现——备忘录模式(三) 撤销功能的实现——备忘录模式(四) 撤销功能的实现——备忘录模式(五) 观察者模式-Observer Pattern 对象间的联动——观察者模式(一) 对象间的联动——观察者模式(二) ...

    内容观察者模式运用

    在实现一些复杂的事件监听的时候,项目里会用到内容观察者模式,自定义内容观察者

    javascript自定义事件功能与用法实例分析

    事件本质是一种消息,事件模式本质上是观察者模式的实现,那么用得上观察者模式的地方,自然也可以也可以用上事件模式。所以,如果: 1、一个目标对象改变,需要多个观察者调整自身的。 比如:我需要元素A点击之后,...

    flex 事件与自定义事件

    如何接收事件?如何做到AS3.0的标准事件编程?...类似JAVA的监听或观察者模式 Event改变的部分很多,正在想怎样用一个有条理的方式来讲解Event和它相关的诸多内容,让我们感到比较容易理解,记忆和接受。

    Java设计模式 版本2

    对象间的联动——观察者模式,处理对象的多种状态及其相互转换——状态模式,算法的封装与切换——策略模式,模板方法模式深度解析,操作复杂对象结构——访问者模式,设计模式与足球,多人联机射击游戏中的设计模式...

    Software-Patterns:Java中的软件设计模式

    观察者模式(java.util) 使用java.util库的模式实现 观察者模式(摆动) 使用awt / swing库实现模式 装饰图案 允许将行为静态或动态地添加到单个对象,而不会影响同一类中其他对象的行为 资料夹: 装饰图案 ...

    深入探索Spring事件监听机制:技术与应用

    这种机制基于观察者模式,由事件(ApplicationEvent)、事件监听器(ApplicationListener)和事件广播器(ApplicationEventMulticaster)三个主要组成部分构成。 事件是发生的动作或事情,其核心是ApplicationEvent...

    北京百度java面试题大全

    Java面试题是针对Java编程语言的技术和知识的一系列问题,用于考察面试者在Java开发方面的能力和...设计模式:涉及常见的设计模式,如单例模式、工厂模式、观察者模式等。 Java框架和技术:包括Spring、Hibernate、My

    JAVA高并发高性能高可用高扩展架构视频教程

    新版本通俗易懂_观察者模式递进时讲解 ibatis连接数据库 高并发之单(多)生产者消费者线程 高并发复用数据库链接技术详解之数据库连接池 类加载器的高级特性(自定义类加器实现加密解密) iBATIS开源主流框架(实现半...

    java高级特性,涵盖了多种java常用的一些例子

    设计模式2(观察者,适配器) 设计模式(Design Pattern)是前辈们对代码开发经验的总结,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是...

    深入浅出设计模式(中文版电子版)

    5.7ObserverPattern(观察者模式) 236 5.7.1定义 236 5.7.2现实例子——拉登现身了 238 5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 ...

    深入浅出设计模式(中文版)

    5.7ObserverPattern(观察者模式) 236 5.7.1定义 236 5.7.2现实例子——拉登现身了 238 5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 ...

    Rxjava2最新视频教程

    1.观察者模式理论篇.mp4 2.观察者模式动手篇.mp4 3.课程大纲介绍.mp4 4.基本使用.mp4 5.线程控制.mp4 6.操作符介绍.mp4 7.登录后获取用户信息.mp4 8.关键词搜索案例.mp4 9.防止按钮重复点击案例.mp4 10.购物车合并...

    Java开发详解.zip

    031114_【第11章:Java常用类库】_观察者设计模式笔记.pdf 031115_【第11章:Java常用类库】_正则表达式笔记.pdf 031116_【第11章:Java常用类库】_定时调度笔记.pdf 031201_【第12章:JAVA IO】_File类笔记.pdf ...

    java 面试题 总结

    JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用...

    java8源码-springboo-quartz:动态界面管理定时任务

    //观察者开发模式 │ ├──lambda //java8的一个新特性 │ ├──config //定时任务的配置 │ ├──controller //任务控制层 │ ├──dao //对应mybatis xml的配置文件 │ ├──entity //实体类 │ ├──...

Global site tag (gtag.js) - Google Analytics