My Blog

通过实例深入理解监听器

之前写过一个简单监听器的实例文章,想要了解的,可以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();
        }
    }
}

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

五、文末

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

在这里插入图片描述

posted @ 2020-07-27 16:13  王心森  阅读(517)  评论(0编辑  收藏  举报