zoukankan      html  css  js  c++  java
  • 通过实例深入理解监听器

    之前写过一个简单监听器的实例文章,想要了解的,可以click:手写一个监听器

    今天我们通过两个实例来加深对监听器的理解!

    一、什么是监听器

    监听器:就是监听某个事件的发生情况,当被监听的事件触发时,发生者(事件源) 就会给注册该事件的监听者(监听器)发送消息,告诉监听者事件消息,同时监听者也可以获得一份事件对象,根据这个对象可以获得相关属性和执行相关操作。

    二、监听器要素

    监听器涉及到的对象有:

    1. 监听者:准备监听事件的人
    2. 被监听者:做出某种行为而被监听的人
    3. 事件:被监听者做出的行为
    4. 监听工具:即监听器

    监听行为,既然要监听,必然要有监听的各种动作,这里主要有两种:

    1. 触发行为:也就是被监听者做出的动作,该动作是这个监听过程的开启点
    2. 响应行为:监听者通过监听工具监听到触发行为后,必然要有的后续动作

    三、实现步骤

    根据监听器要素可知,如果要达到监听某一行为的目的,我们需要完成各对象和行为的创建,那么执行步骤及执行顺序如下:

    1. 定义监听器接口,定义监听动作
    2. 创建监听者、被监听者,将监听器作为内部属性,创建注册方法
    3. 创建事件对象,将监听者与被监听者作为属性
    4. 实现监听器接口,分别创建监听者、被监听者的监听实例
    5. 在监听者内部创建触发行为
    6. 在被监听者内部创建响应行为

    至此,按照以上顺序,我们就创建好了监听器的各个对象及行为。那么接下来,我们开始编码实现监听器效果!

    四、实例

    1.场景描述

    我们通过实例模拟监听器行为,考虑以下场景:

    某工地,包工头老板为防止员工缺勤情况,要求员工到岗后,需向其签字报到,然后开始立即工作!

    那么,此时,在这种场景下,我们来根据监听器要素来进行分析:

    监听者:包工头老板
    被监听者:员工
    事件:员工到岗
    监听工具:报到表

    触发行为:签字报到
    响应行为:立即开始工作

    2.代码实现

    代码中使用了插件lombok,请各位同学自行引入!

    1)定义监听器接口

    package cn.wxson.listener.arriver;
    
    /**
     * Title 监听器
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    public interface Listener {
        /**
         * 监听行为
         *
         * @param event 事件
         */
        void notice(Event event);
    }
    

    2)监听者、被监听者

    监听者、被监听者内部的触发行为、响应行为已一并贴出来了,后面不再进行第5、6步的操作,特此说明!

    package cn.wxson.listener.arriver;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 员工
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    @Setter
    @Getter
    public class Employer {
    
        private String name;
        private Listener listener;
    
        public Employer(String name) {
            this.name = name;
        }
    
        public void register(Listener listener) {
            this.listener = listener;
        }
    
        public void arrive() {
            if (listener != null) {
                Event event = new Event(this);
                listener.notice(event);
            } else {
                log.info("[员工到达公司,但没有向老板报到]");
            }
        }
    }
    
    package cn.wxson.listener.arriver;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 包工头老板
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    @Setter
    @Getter
    public class Boos {
        private String name;
        private Listener listener;
    
        public Boos(String name) {
            this.name = name;
        }
    
        public void register(Listener listener) {
            this.listener = listener;
        }
    
        public void order() {
            if (listener != null) {
                Event event = new Event(this);
                listener.notice(event);
            } else {
                log.info("[包工头没有告诉员工,到达公司需要签字报告]");
            }
        }
    }
    

    3)创建事件对象

    package cn.wxson.listener.arriver;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.Setter;
    
    /**
     * Title 雇员到达公司事件
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Setter
    @Getter
    @AllArgsConstructor
    public class Event {
        private Boos boos;
        private Employer employer;
    
        public Event(Boos boos) {
            this.boos = boos;
        }
    
        public Event(Employer employer) {
            this.employer = employer;
        }
    }
    

    4)实现监听器接口,分别创建监听者、被监听者的监听实例

    package cn.wxson.listener.arriver;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 员工到达公司的监听器
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    public class EmployerListener implements Listener {
    
        @Override
        public void notice(Event event) {
            Employer employer = event.getEmployer();
            log.info("[员工{}已到公司,准备随时开始上班]", employer.getName());
        }
    }
    
    package cn.wxson.listener.arriver;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 老板下达工作命令的监听器
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    public class BoosListener implements Listener {
    
        @Override
        public void notice(Event event) {
            Boos boos = event.getBoos();
            log.info("[老板{}已知道员工到达公司,现在命令他立即开始工作}]", boos.getName());
        }
    }
    

    5)在监听者内部创建触发行为

    已包含在第2)步的代码当中!

    6.)在被监听者内部创建响应行为

    已包含在第2)步的代码当中!

    7)创建测试用例

    我们来创建测试类,进行效果测试,代码含义已很详细,不做过多说明!

    package cn.wxson.listener.arriver;
    
    /**
     * Title 测试类
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    public class Domain {
    
        public static void main(String[] arg) {
            // 创建员工到达公司的监听器
            EmployerListener employerListener = new EmployerListener();
            // 创建员工:Tom,并为其注册监听器
            Employer employer = new Employer("Tom");
            employer.register(employerListener);
    
            // 创建包工头下达工作命令的监听器
            BoosListener boosListener = new BoosListener();
            // 创建包工头:马云,并为其注册监听器
            Boos boos = new Boos("马云");
            boos.register(boosListener);
    
            // Tom到达公司
            employer.arrive();
            // 包工头下达命令
            boos.order();
        }
    }
    

    执行结果:
    马老板的监听效果
    那么以上就是我们对一个简单监听器的具体实现,接下来,我们进行更多扩展!

    3.功能扩展

    上面的实例场景是单个员工的行为监听,那如果是多个呢?

    我们假设,马老板手头有项工作,需要手下5个员工全部到场的情况,一起工作才能完成,少一个都不行,那么,我们该怎么监听呢?

    注:同上一个场景,每个员工到来后,都需要签字报到!

    1)定义监听器接口

    package cn.wxson.listener.work;
    
    /**
     * Title 监听器
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    public interface Listener {
        /**
         * 员工到达公司,并报告给老板
         *
         * @param event 事件
         */
        void arrive(Event event);
    
        /**
         * 下达上班命令
         *
         * @param event 事件
         */
        void order(Event event);
    }
    

    2)监听者、被监听者

    监听者、被监听者内部的触发行为、响应行一并贴出来,后面不再进行第5、6步的操作!

    package cn.wxson.listener.work;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 雇员
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    @Setter
    @Getter
    public class Employer {
    
        private String name;
        private Listener listener;
    
        public Employer(String name) {
            this.name = name;
        }
    
        public void register(Listener listener) {
            this.listener = listener;
        }
    
        public void arrive() {
            if (listener != null) {
                Event event = new Event(this);
                listener.arrive(event);
            } else {
                log.info("[员工到达公司,但没有向包工头报到]");
            }
        }
    }
    
    package cn.wxson.listener.work;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 包工头老板
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    @Setter
    @Getter
    public class Boos {
        private String name;
        private Listener listener;
    
        public Boos(String name) {
            this.name = name;
        }
    
        public void register(Listener listener) {
            this.listener = listener;
        }
    
        public void order() {
            if (listener != null) {
                Event event = new Event(this);
                listener.order(event);
            } else {
                log.info("[包工头没有告诉员工,到达公司需要签字报告]");
            }
        }
    }
    

    3)创建事件对象

    package cn.wxson.listener.work;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.Setter;
    
    /**
     * Title 员工到达公司事件
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Setter
    @Getter
    @AllArgsConstructor
    public class Event {
        private Boos boos;
        private Employer employer;
    
        public Event(Boos boos) {
            this.boos = boos;
        }
    
        public Event(Employer employer) {
            this.employer = employer;
        }
    }
    

    4)实现监听器接口,创建监听实例

    package cn.wxson.listener.work;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * Title 工作监听器
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    @Slf4j
    public class WorkListener implements Listener {
    
        /**
         * 员工总数量
         */
        private static final Long TOTAL_NUM = 5L;
        /**
         * 到达公司的员工数量
         */
        private static Long num = 0L;
    
        @Override
        public void arrive(Event event) {
            log.info("[员工"{}"到达公司}]", event.getEmployer().getName());
            num++;
        }
    
        @Override
        public void order(Event event) {
            if (num.intValue() == TOTAL_NUM.intValue()) {
                log.info("[全体员工就位,老板"{}"命令开始工作]", event.getBoos().getName());
                num = 0L;
            } else {
                log.info("[现有{}名员工到达公司,还有{}名员工没有到达]", num, TOTAL_NUM - num);
            }
        }
    }
    

    5)在监听者内部创建触发行为

    已包含在第2)步的代码当中!

    6.)在被监听者内部创建响应行为

    已包含在第2)步的代码当中!

    7)创建测试用例

    我们来创建测试类,进行效果测试,代码含义已很详细,不做过多说明!

    package cn.wxson.listener.work;
    
    /**
     * Title 测试类
     *
     * @author Ason(18078490)
     * @date 2020-07-23
     */
    public class Domain {
    
        public static void main(String[] arg) {
            // 创建开始工作的监听器
            WorkListener workListener = new WorkListener();
            // 任命老板马云
            Boos boos = new Boos("马云");
            // 为老板赋权--下达工作的权限
            boos.register(workListener);
            // 模拟5个员工陆续到达公司
            for (int i = 1; i <= 5; i++) {
                Employer employer = new Employer("员工" + i);
                employer.register(workListener);
                employer.arrive();
                boos.order();
            }
        }
    }
    

    执行结果:
    马老板监听所有员工

    五、文末

    上面,我们对监听器的各个要素进行了详细说明,监听步骤也做了实例演示,如果这些能对你有一些帮助的话,本人就达到目的了,在此,感谢阅读!

    在这里插入图片描述

  • 相关阅读:
    正则表达式
    JavaIO详解
    Java集合类详解
    Java虚拟机原理图解
    关于Java中按值传递和按引用传递的问题详解
    图的建立(邻接矩阵)+深度优先遍历+广度优先遍历+Prim算法构造最小生成树(Java语言描述)
    The 70th problem,UVa10396 Vampire Numbers
    二叉树的实现(Java语言描述)
    编程之路
    AngularJS 开发中常犯的10个错误
  • 原文地址:https://www.cnblogs.com/ason-wxs/p/13385997.html
Copyright © 2011-2022 走看看