【Java】监听器的理解和开发

by img Microanswer 创建时间:May 26, 2019 4:15:45 PM 

标签: java 监听器 回调 回调函数 接口



重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

一、序

本文将对Java开发中常常使用到的一种开发技术(监听器)做一个比较简单、白话一点的简述和讨论。做Java开发的贤士都知道,这两种开发技术在实际应用中经常被使用到,但是对于刚刚“出山”的贤士们来说,从代码上直接理解起来还是有点吃力。

这种开发方式对初学者来说一直都是一知半解的存在,我想一部分原因应该归咎于在接受这方面知识得时候,对方的描述比较官方,让我们理解起来不是很通透。我将以更为白话一点的语言将这个技术做一个浅显的解释,希望能够对初学的贤士有一点帮助。

二、引入场景

小保是一个零售店老板,有一天,小保有一批货物要送到一家客户去,但由于小保人手不够,自己又要看店,只好找一个人帮他将这批货物送到客户家里去。通过关系,小保找到了一个派送师傅,并嘱托派送师傅,货物送到了的时候,要第一时间通知小保, 为了能够让通知信息及时送到,小保还给了派送师傅一个对讲机(信号范围覆盖4个星系,滑稽)。

派送师傅很快就取到了货物,开着小电瓶开始送货去了,不一会儿,小保这边的对讲机里传来:小保老板,你的货我已经安全送到客户这里了。小保嘴巴一撇,回复到:好,好!谢谢了。

对于这样的情景,我们可以总结出下面一些要点信息:
1、小保提出送货需求。
2、派送师傅执行送货,同时携带对讲机,便于通知小保。
3、小保收到派送成功的消息。

三、要点分析与代码结合

要感谢Java的创始人詹姆斯·高斯林(百度百科),面向对象的Java语言使你可以将上面的现实场景和你的程序代码一一对应起来。

下面就将已程序代码的方式和现实场景结合起来,没有什么东西比贴近生活更容易理解了,相信你也能看懂。

0、准备

小保能够进行这次送货给客户,因为小保是零售店老板,他这儿有客户需要的东西。正是因为小保是老板的前提,才有了接下来的为客户送货的事情能够顺利发生。

同样的,咱们程序为了正常执行,需要先有一个完整的可以开始运行的前提,所以,先准备好需程序测试类。

public class Test {
    
    // main 方法是每一个java程序的入口函数。
    public static void main(String[] args) {
        // ...
    }
}

1、建立配送员

要完成这次货物的配送,需要派送师傅来完成,所以,必不可少的需要建立一个派送师傅类出来,使用 Transporter 类来表示:

public class Test {
    
    // 派送师傅类。
    static class Transporter {
        
    }
    
    public static void main(String[] args) {
        // ...
    }
}

同时,派送员有一个送东西的功能:

public class Test {
    
    // 派送师傅类。
    static class Transporter {    
        // 添加送东西的功能。
        public void sendGood(String goodName) {
            System.out.println("正在配送:" + goodName);
        }
    }
    
    public static void main(String[] args) {
        // ...
    }
}

现在,你可以做一个测试了,在 main 方法 new 一个派送员,然后进行派送:

public static void main(String[] args) {
    Transporter transMan = new Transporter();
    
    // 使用new 出来的派送师傅进行商品派送。
    transMan.sendGood("娃哈哈");
}

2、携带对讲机

如果整个需求就如上面的代码就完成了的话,那这个世界岂不大乱。派送员拿着“娃哈哈”灰溜溜的就走了,送到没送到,我也不知道。小保是要保证货品必须到达客户手中的,为了确信这件事,小保特地给了派送员一个对讲机。程序也不例外,要知道 Transporter 到底 有没有将货物送到,也要加入对讲机,这里使用BBtalk类进行对讲机的模拟,继续完善整个Test类的代码:

public class Test {
    
    // 派送师傅类。
    /* {...} 此处为了节省篇幅已隐藏,实际运行请不要这样写,下同 */
    
    // 对讲机类
    static class BBtalk {
        // 对讲机有传话功能
        public void speak(String word) {
            System.out.println(word);
        }
    } 
    
    public static void main(String[] args) {
        // ...
    }
}

对讲机有了,现在可以将对讲机交给派送师傅了,在程序里,需要为派送师傅类添加一个可以变量用来保存对讲机,同时,让派送师傅在派送成功后使用对讲机传话:

public class Test {
    
    // 派送师傅类。
    static class Transporter {    
        // 对讲机变量。
        BBtalk bBtalk;
        
        // 构造函数初始化对讲机
        Transporter(BBtalk bBtalk) {
            this.bBtalk = bBtalk;
        }
        
        // 送东西的功能。
        public void sendGood(String goodName) {
            System.out.println("正在配送:" + goodName);
            
            // 配送完成,使用对讲机传话。
            bBtalk.speak(goodName + ",已经成功送到!");
        }
    }
    
    // 对讲机类
    /* {...} */
    
    public static void main(String[] args) {
        // ...
    }
}

现在,配送员送完货之后咱们知道了送货员什么时候送到了,写上测试:

public class Test {
    
    // 派送师傅类。
    /* {...} */
    
    // 对讲机类
    /* {...} */
    
    public static void main(String[] args) {
        
        // 建立对讲机
        BBtalk bBtalk = new BBtalk();
        
        // 建立配送师傅,同时将对讲机交给配送师傅。
        Transporter transMan = new Transporter(bBtalk);
        
        // 配送师傅进行配送。
        transMan.sendGood("娃哈哈");
    }
}

3、小结

在上面的整个过程中BBtalk就充当监听器,Transporter充当被监听的东西。派送员一但派送完成,就用对讲机传话。被监听的一但完成某操作,就调用监听器的方法,这就叫回调(通常是以监听器的角度来说,这就叫回调),BBtalkspeak方法称之为[回调方法]。但是在实际开发中,通常不会为一个监听器专门写一个类,而是以一个接口的方式出现。 继续修改代码,实现技能到应用,添加派送监听器:

public class Test {
    
    // 派送师傅类。
    static class Transporter {    
        // 对讲机变量。 -  不再使用对讲机。
        // BBtalk bBtalk;
        
        // 使用监听器
        TransportListener transportListener;
        
        // 构造函数初始化对讲机 - 对讲机也别初始化了。
        // Transporter(BBtalk bBtalk) {
        //     this.bBtalk = bBtalk;
        // }
        
        // 使用监听器初始化。
        Transporter(TransportListener transportListener) {
            this.transportListener = transportListener;
        }
        
        // 送东西的功能。
        public void sendGood(String goodName) {
            System.out.println("正在配送:" + goodName);
            
            // 配送完成,使用对讲机传话。 - 不使用对讲机传话了。
            // bBtalk.speak(goodName + ",已经成功送到!");
            
            // 使用监听器,调起货物派送完成回调方法
            this.transportListener.onTransSuccess(goodName);
        }
    }
    
    // 对讲机类
    /* {...} */
    
    // 派送监听器接口。
    interface TransportListener {
        // 当货物派送完成,调用该方法。
        void onTransSuccess(String goodName);
    }
    
    public static void main(String[] args) {
        // ..
    }
}

使用了监听器,下面再一次进行测试:

public class Test {
    
    // 派送师傅类。
    /* {...} */
    
    // 对讲机类
    /* {...} */
    
    // 派送监听器接口。
    /* {...} */
    
    public static void main(String[] args) {
        // 构建派送师傅。
        // 由于监听器是一个接口了,此处必须实现该接口中的方法。
        // 所以,构建一个匿名内部类,直接传入构造函数。
        Transporter transMan = Transporter(new TransportListener() {
            
            // 当派送完成时,此方法会调起。
            public void onTransSuccess(String goodName) {
                System.out.println(goodName + ",已派送成功!");
            }
        });
        
        // 派送员进行派送
        transMan.sendGood("娃哈哈");
    }
}

Perfect!

四、总结

对监听器的理解多多少少有一点接口-interface方面的知识,在了解了接口相关知识后,理解相对简单。万变不离其中,都是一句话:要调用某个方法,就要拿到这个对象,要有这个对象,就要有地方让别人能为这个对象赋值!

全文完, 转载请注明出处。 对你有帮助?不如赞一个吧:
发表评论(发表评论需要登录,你现在还没有登录。)
你需要先登录才可以评论。

评论列表 (0条)