博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java回调方法、钩子方法以及模板方法模式
阅读量:5763 次
发布时间:2019-06-18

本文共 2813 字,大约阅读时间需要 9 分钟。

在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象,其处理事件的方法叫做回调方法。(摘自百度百科)

那么通过上面那句话将百度百科中的“回调函数”翻译成JAVA版:回调方法就是一个通过回调对象的引用(java中的引用存的是对象的地址)调用的方法。如果你把

回调对象的引用(地址)作参数传递给另一个方法,当这个引用被用来调用其所指向的方法时,我们就说这是回调方法。回调方法不是由该方法的实现方直接调用,

而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

 

      下面我们来通过一个小需求来实现回调,需求为:王钢蛋去餐厅打饭,餐厅服务员根据其饭量为其打饭。我们先构思下,首先要有个接口,接口中定义个抽象方法为 饭量(回调接口);其次创建王钢蛋(回调类),让王钢蛋实现这个接口,并想好其饭量(回调方法);最后创建餐厅,餐厅服务员(另一方)接待王钢蛋(回调对 象)并根据其提供的饭量(回调方法)打饭(特定事件,该事件会调用回调方法)。上代码:

 

/**  * 顾客,去食堂吃饭有个前提,要告诉服务员其饭量,才会给你盛饭  * @author coder  * */ interface Client{
/** * 告诉服务员其饭量 * @return */ public String appetite(); } class WangGangDan implements Client{
@Override public String appetite() {
return "一车米饭"; } } /** *食堂 */ class Restaurant{
/** * 打饭方法,前提是客户要告知服务员你的饭量,他会根据你的饭量给你“盛”饭 * @param client 排队的客户 * @return */ public String dozenRice(Client client){
return "盛了"+client.appetite(); } } public class Test1 { //业务处理类,老王去打饭 public static void main(String[] args) {
WangGangDan laowang=new WangGangDan(); //王钢蛋以别名laowang去食堂要饭 Restaurant waiter=new Restaurant(); String dozenRice=waiter.dozenRice(laowang); System.out.println(dozenRice); //最后老王“盛了一车米饭” //但是通常我们打饭时不会告诉服务员我们叫什么,这样太麻烦了,那么可不可以只告诉服务员 //饭量多少就给我们打饭呢?按常理来说我们去餐厅也只会要一次饭。 //匿名内部类多用来实现回调,简便 String dozenRice1=waiter.dozenRice(new Client(){ @Override public String appetite() {
return "一锅米饭"; }}); System.out.println(dozenRice1); } }

         这里将利用模板方法模式来说明钩子方法是什么,许多设计模式都用到了回调,钩子之类的概念,这些基础点理解了,有些模式也就不那么晦涩难懂了,稍微改写下上面的代码就可以:

/**  *  模板方法模式:在一个方法中定义一个算法的骨架,而将一些步  *  骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情  *  况下,重新定义算法中的某些步骤。  * 【钩子方法】:原理就是实现为空的方法,在某任务之前、之后、  *  执行中、报异常后调用的方法(是不是有种熟悉的感觉)。  *  通常钩子方法是通过抽象类或是本类中的空方法来实现的。  * */ abstract class Client{
/** * 【模板方法】 */ public void templateMethod(){
before(); appetite(); after(); } /** * 【钩子方法】在盛饭前(一个空的实现) */ protected void before(){}; /** * 【抽象方法】告诉服务员其饭量 * @return 饭量 */ public abstract void appetite(); /** * 【具体方法】盛饭后 */ private void after(){
//实际项目这里是共有的业务逻辑 System.out.println("拿筷子,找桌子,开吃..."); } } /** *食堂 */ class Restaurant{
/** * 打饭方法,前提是客户要告知服务员你的饭量,他会根据你的饭量给你“盛”饭 * @param client 排队的客户 * @return */ public void dozenRice(Client client){
client.templateMethod(); } } public class Test1 { //业务处理类,老王去打饭 public static void main(String[] args) {
Restaurant waiter=new Restaurant(); waiter.dozenRice(new Client(){
@Override protected void before() {
System.out.println("对服务员吹胡子瞪眼!!"); } @Override public void appetite() {
System.out.println("盛了一锅米饭"); }}); } }

 

 

 

 

 

    

转载地址:http://eqgkx.baihongyu.com/

你可能感兴趣的文章
手把手教你测——上网快鸟
查看>>
SQL server 2014 安装
查看>>
Linux 系统 TCP优化
查看>>
xamarin.Android 选择本地图片、拍摄图片、剪裁图片
查看>>
MAC系统 华为EC1261 3G上网方法
查看>>
Java EE (5) -- Java EE 6 JavaServer Faces Developer Certified Expert(1z0-896)
查看>>
【玩转开源】BananaPi R2 —— 第三篇 基于Openwrt开发一个简单的路由器
查看>>
(生产)vue-lazyload - 图片延迟加载
查看>>
被人遗忘的MAX_FILE_SIZE文件上传限制大小参数
查看>>
python数据类型
查看>>
隐藏index.php
查看>>
CF 590D Top Secret Task【dp递推+滚动数组】【好题】
查看>>
守望者的逃离
查看>>
关于STM32单片机GPIO口上拉与下拉输入
查看>>
【学习笔记】python2的print和python3的print()
查看>>
UVA 10462 Is There A Second Way Left?(次小生成树&Prim&Kruskal)题解
查看>>
Android Studio快捷键快速入门
查看>>
PHP打印金字塔---自己的实践练习题目
查看>>
vue.js学习笔记(二):如何加载本地json文件
查看>>
CRM系统如何帮助企业实现互联网+?
查看>>