• JDK自带的监听器模式


     《观察者模式与监听模式

     《JDK自带的观察者模式

    JDK自带的监听器模式

    ApplicationEvent事件机制源码分析

    监听模式

       当事件源对象上发生操作时,将会调用事件监听器的一个方法,并在调用该方法时把事件对象传递过去。

    监听器模式中的3个角色:

    • 事件源:具体的事件源,注册特定的监听,才可以对事件进行响应。
    • 事件对象:封装了事件源对象以及事件相关的信息,是在事件源和事件监听器之间传递信息的角色。
    • 事件监听器:监听事件,并进行事件处理或者转发,必须注册在事件源上。

    一句话,事件源产生事件,事件带有事件源,监听器监听事件。

    JDK中当然有现成的事件模型类 

    监听器模式和观察者模式大同小异,但要比观察者模式复杂一些。一些逻辑需要手动实现,比如注册监听器,删除监听器,获取监听器数量等等,这里的eventObject也是你自己实现的。

    先看看JDK中的监听器类图

    角色之三:事件监听器

    package java.util;
    
    /**
     * A tagging interface that all event listener interfaces must extend.
     * @since JDK1.1
     */
    public interface EventListener {
    }

    简单到不能再简单了,对吧,甚至连一个声明的方法都没有,那它存在的意义在哪?还记得面向对象中的上溯造型吗,所以它的意义就在于告诉所有的调用者,我是一个监听器。

    角色之二&一:事件对象及事件对象里的事件源

    再来看看事件,即Event或EventObject结尾的那个类,里面含有getSource方法,返回的就是事件源,

    package java.util;
    
    /**
     * <p>
     * The root class from which all event state objects shall be derived.
     * <p>
     * All Events are constructed with a reference to the object, the "source",
     * that is logically deemed to be the object upon which the Event in question
     * initially occurred upon.
     *
     * @since JDK1.1
     */
    
    public class EventObject implements java.io.Serializable {
    
        private static final long serialVersionUID = 5516075349620653480L;
    
        /**
         * The object on which the Event initially occurred.
         */
        protected transient Object  source;
    
        /**
         * Constructs a prototypical Event.
         *
         * @param    source    The object on which the Event initially occurred.
         * @exception  IllegalArgumentException  if source is null.
         */
        public EventObject(Object source) {
            if (source == null)
                throw new IllegalArgumentException("null source");
    
            this.source = source;
        }
    
        /**
         * The object on which the Event initially occurred.
         *
         * @return   The object on which the Event initially occurred.
         */
        public Object getSource() {
            return source;
        }
    
        /**
         * Returns a String representation of this EventObject.
         *
         * @return  A a String representation of this EventObject.
         */
        public String toString() {
            return getClass().getName() + "[source=" + source + "]";
        }
    }

    这个类也很简单,如果说观察者模式中的上层类和结果还带了不少逻辑不少方法的话,那么事件驱动模型中的上层类和接口简直看不到任何东西。没错,

    事件驱动模型中,JDK的设计者们进行了最高级的抽象,就是让上层类只是代表了:我是一个事件(含有事件源),或,我是一个监听者!

     示例:

    package com.dxz.listener2;
    
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    /**
     * 事件源.
     */
    public class EventSourceObject {
        private String name;
        // 监听器容器
        private Set<CusEventListener> listener;
    
        public EventSourceObject() {
            this.listener = new HashSet<CusEventListener>();
            this.name = "defaultname";
        }
    
        // 给事件源注册监听器
        public void addCusListener(CusEventListener cel) {
            this.listener.add(cel);
        }
    
        // 当事件发生时,通知注册在该事件源上的所有监听器做出相应的反应(调用回调方法)
        protected void notifies() {
            CusEventListener cel = null;
            Iterator<CusEventListener> iterator = this.listener.iterator();
            while (iterator.hasNext()) {
                cel = iterator.next();
                cel.fireCusEvent(new CusEvent(this));
            }
        }
    
        public String getName() {
            return name;
        }
    
        /**
         * 模拟事件触发器,当成员变量name的值发生变化时,触发事件。
         * @param name
         */
        public void setName(String name) {
            if (!this.name.equals(name)) {
                this.name = name;
                notifies();
            }
        }
    }
    
    package com.dxz.listener2;
    
    import java.util.EventListener;
    
    /**
     * 事件监听器,实现java.util.EventListener接口。定义回调方法,将你想要做的事放到这个方法下,因为事件源发生相应的事件时会调用这个方法。
     */
    public class CusEventListener implements EventListener {
        // 事件发生后的回调方法
        public void fireCusEvent(CusEvent e) {
            EventSourceObject eObject = (EventSourceObject) e.getSource();
            System.out.println("My name has been changed!");
            System.out.println("I got a new name,named \"" + eObject.getName() + "\"");
        }
    }
    
    package com.dxz.listener2;
    
    import java.util.EventObject;
    
    /**
     * 事件类,用于封装事件源及一些与事件相关的参数.
     */
    public class CusEvent extends EventObject {
        private static final long serialVersionUID = 1L;
        private Object source;// 事件源
    
        public CusEvent(Object source) {
            super(source);
            this.source = source;
        }
    
        public Object getSource() {
            return source;
        }
    
        public void setSource(Object source) {
            this.source = source;
        }
    }
    
    package com.dxz.listener2;
    
    public class MainTest {
    
        public static void main(String[] args) {
            EventSourceObject object = new EventSourceObject();
            // 注册监听器
            object.addCusListener(new CusEventListener() {
                @Override
                public void fireCusEvent(CusEvent e) {
                    super.fireCusEvent(e);
                }
            });
            // 触发事件
            object.setName("AiLu");
        }
    }

    结果:

    My name has been changed!
    I got a new name,named "AiLu"

     1. 事件

    事件一般继承自java.util.EventObject类,封装了事件源对象及跟事件相关的信息。
    2. 事件源
    事件源是事件发生的地方,由于事件源的某项属性或状态发生了改变(比如BUTTON被单击、TEXTBOX的值发生改变等等)导致某项事件发生。换句话说就是生成了相应的事件对象。因为事件监听器要注册在事件源上,所以事件源类中应该要有盛装监听器的容器(List、Set等等)。
    3. 事件监听器
    事件监听器实现java.util.EventListener接口,注册在事件源上,当事件源的属性或状态改变时,取得相应的监听器调用其内部的回调方法。
    事件、事件源、监听器三者之间的联系
    事件源-----产生----->事件------>被事件监听器发现------>进入事件处理代码

  • 相关阅读:
    Java 泛型 泛型的约束与局限性
    Java 泛型 泛型方法
    Java 泛型 泛型数组
    Java 泛型 协变性、逆变性
    Java 泛型 协变式覆盖和泛型重载
    Java 泛型 泛型代码和虚拟机
    Insertion Sort List
    Remove Duplicates from Sorted List II
    String to Integer (atoi)
    SpringMvc源码入门
  • 原文地址:https://www.cnblogs.com/duanxz/p/2855979.html
Copyright © 2020-2023  润新知