`

[原]观察者模式-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实现观察者模式-自定义的观察者接口和主题类

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

    java观察者模式demo----未使用java工具类

    在Java中,标准的观察者模式实现是通过`java.util.Observable`类和`java.util.Observer`接口来完成的,但本示例特别指出未使用这两个内置工具类,而是完全自定义实现了观察者模式。 观察者模式的主要组件包括: 1. ...

    java自定义事件

    这种设计模式被称为观察者模式,是Java中常用的一种多线程同步和异步通信方式。 在Java AWT和Swing库中,已经预定义了许多内置的事件类型,如鼠标事件、键盘事件、窗口事件等。但有时,这些预定义的事件并不能满足...

    Java内置观察者模式

    本文将深入探讨Java内置的观察者模式,包括其原理、实现方式以及实际应用。 ### 观察者模式的核心概念 1. **主题(Subject)**:被观察的对象,也就是发出通知的一方。在Java中,通常通过实现`java.util....

    自定义观察者模式

    在Java中,我们可以自定义观察者模式来实现特定的需求。 首先,观察者模式的核心是Subject(主题)和Observer(观察者)两个角色。Subject维护一个Observer集合,并提供添加、删除观察者的方法,以及通知所有观察者...

    观察者模式java实现观察者设计模式

    在Java中,我们可以利用Java提供的内置监听器机制来实现观察者模式,例如`ApplicationListener`和`ApplicationEvent`,这两个类主要用于Swing或JavaFX应用程序中的事件处理。 首先,我们来看`ApplicationListener`...

    教你如何在java中自定义事件

    在Java AWT和Swing库中,事件模型是基于观察者模式的。事件通常由一个对象(称为事件源)生成,然后被传递到感兴趣的其他对象(称为事件监听器)。例如,当用户点击按钮时,按钮对象会触发一个ActionEvent,该事件会...

    观察者模式代码(JAVA)

    观察者模式不仅限于`java.util`包中的实现,也可以自定义观察者和被观察者类,这样可以更灵活地处理不同类型的事件和状态变化。同时,注意避免过度使用观察者模式,因为它可能导致过多的回调和复杂的依赖关系,影响...

    java里的自定义实现事件

    这个例子展示了如何在Java中通过观察者模式自定义实现事件。在实际项目中,可能会有更复杂的需求,如多线程处理事件、异步事件等,但基本思路是相似的。通过这种方式,我们可以实现类似于C#中事件的机制,使代码更加...

    java观察者模式Demo

    观察者模式是软件设计模式中的一种行为...总的来说,"java观察者模式Demo"提供了一个使用Java标准库实现观察者模式的例子,这对于学习和理解设计模式是非常有帮助的,同时通过自定义实现还能进一步深入理解其工作原理。

    Java观察者模式代码全解析

    Java观察者模式是一种设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在软件工程中广泛应用,尤其在事件驱动和发布/订阅系统中。...

    观察者模式Vs事件委托Demo

    在编程领域,观察者模式(Observer Pattern)和事件委托(Event Delegation)是两种常见的设计模式,它们在处理对象间的交互和通信时起到关键作用。本文将深入探讨这两种模式的概念、工作原理及其在Java中的应用。 ...

    design-pattern-java.pdf

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

    java实现观察者模式

    在Java中,观察者模式可以通过Java的内置API `java.util.Observable` 和 `java.util.Observer` 类来实现。`Observable` 类代表被观察的对象,而 `Observer` 接口则表示观察者。以下是对这两个关键类的详细解释: 1....

    观察者模式与JavaBeans事件

    在JavaBeans中,事件处理是通过观察者模式实现的。事件源(Event Source)是发布事件的对象,而事件监听器(Event Listener)是接收并处理这些事件的对象。JavaBeans事件包括动作事件、属性更改事件等,它们通过事件...

    设计模式--Java语言版本

    5. **观察者模式**(Subject-Observer):定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。Java.util.Observable和Observer接口是其核心。 6. **...

    java设计模式-观察者 小案例

    在Java中,观察者模式通常通过`java.util.Observable`类和`java.util.Observer`接口来实现。在这个"java设计模式-观察者 小案例"中,我们可能会看到一个简单的模拟,雅典娜作为观察者,而其他角色(如圣斗士)则是被...

    Java线程池及观察者模式解决多线程意外死亡重启问题

    Java线程池是Java并发编程中的重要组成部分,它...总之,通过Java线程池和观察者模式的结合,我们可以构建一个健壮的多线程系统,即使在部分线程意外终止的情况下,也能及时发现并采取措施恢复,确保系统的稳定运行。

    设计模式之观察者模式(Observer)

    观察者模式在Java中得到了很好的支持,`java.util.Observable`和`java.util.Observer`是Java标准库提供的观察者模式实现。开发者可以方便地利用这两个类实现观察者模式,也可以根据实际需求自定义观察者接口和主题类...

    ACTIVE事件发射器允许您注册多个观察者,但在没有观察者时将事件排入队列 -Java-下载

    在给定的标题和描述中提到的"ACTIVE事件发射器"是一个特定实现,它扩展了Java中的事件处理机制,允许注册多个观察者,并且在没有观察者的情况下将事件暂存到队列中。 这个"ACTIVE事件发射器"可能是自定义的库或者...

Global site tag (gtag.js) - Google Analytics