浅谈对java callback 以及 “钩子”的理解
1、首先,callback和“钩子”是两个完全不同的概念:
callback是指:由我们自己实现的,但是预留给系统调用的函数,我们自己是没有机会调用的,但是我们知道系统在什么情况下会调用该方法。
“钩子”是指:声明在抽象类中的方法,只有空的或默认的实现,通常应用在模板设计模式中,让子类可以对算法的不同点进行选择或挂钩,要不要挂钩由子类决定。
2、在这里,我主要介绍callback,顺道分析了一下何为“钩子”。那么什么是回调函数呢?我认为,回调函数就是预留给系统调用的函数,而且我们往往知道该函数被调用的时机。这里有两点需要注意:
第一点,我们写回调函数不是给自己调用的,而是准备给系统在将来某一时刻调用的;
第二点,我们应该知道系统在什么情形下会调用我们写的回调函数。
一句话,回调是一种双向调用模式,什么意思呢,就是说,被调用方在被调用时也会调用对方,这就叫回调。“If you call me, i will call back”。
不理解?没关系,先看看这个可以说比较经典的使用回调的方式:
class A实现接口InA ——背景1
class A中包含一个class B的引用b ——背景2
class B有一个参数为InA的方法test(InA a) ——背景3
A的对象a调用B的方法传入自己,test(a) ——这一步相当于you call me
然后b就可以在test方法中调用InA的方法 ——这一步相当于i call you back
3,测试类
4,输出结果:
Making tea...
Boiling water
Dripping Coffee through filter
Pouring into cup
Would you like milk and sugar with your coffee (y/n)?
y
Adding Sugar and Milk
1、首先,callback和“钩子”是两个完全不同的概念:
callback是指:由我们自己实现的,但是预留给系统调用的函数,我们自己是没有机会调用的,但是我们知道系统在什么情况下会调用该方法。
“钩子”是指:声明在抽象类中的方法,只有空的或默认的实现,通常应用在模板设计模式中,让子类可以对算法的不同点进行选择或挂钩,要不要挂钩由子类决定。
2、在这里,我主要介绍callback,顺道分析了一下何为“钩子”。那么什么是回调函数呢?我认为,回调函数就是预留给系统调用的函数,而且我们往往知道该函数被调用的时机。这里有两点需要注意:
第一点,我们写回调函数不是给自己调用的,而是准备给系统在将来某一时刻调用的;
第二点,我们应该知道系统在什么情形下会调用我们写的回调函数。
一句话,回调是一种双向调用模式,什么意思呢,就是说,被调用方在被调用时也会调用对方,这就叫回调。“If you call me, i will call back”。
不理解?没关系,先看看这个可以说比较经典的使用回调的方式:
class A实现接口InA ——背景1
class A中包含一个class B的引用b ——背景2
class B有一个参数为InA的方法test(InA a) ——背景3
A的对象a调用B的方法传入自己,test(a) ——这一步相当于you call me
然后b就可以在test方法中调用InA的方法 ——这一步相当于i call you back
经典代码:
//相当于接口InA
public interface BoomWTC{
//获得拉登的决定
public benLaDengDecide();
// 执行轰炸世贸
public void boom();
}
//相当于class A
public class At$911 implements BoomWTC{//相当于【背景1】
private boolean decide;
private TerroristAttack ta;//相当于【背景2】
public At$911(){
Date now=new Date();
SimpleDateFormat myFmt1=new SimpleDateFormat("yy/MM/dd HH:mm");
this.dicede= myFmt.format(dt).equals("01/09/11 09:44");
this.ta=new TerroristAttack();
}
//获得拉登的决定
public boolean benLaDengDecide(){
return decide;
}
// 执行轰炸世贸
public void boom(){
ta.attack(new At$911);//class A调用class B的方法传入自己的对象,相当于【you call me】
}
}
//相当于class B
public class TerroristAttack{
public TerroristAttack(){
}
public attack(BoomWTC bmw){//这相当于【背景3】
if(bmw.benLaDengDecide()){//class B在方法中回调class A的方法,相当于【i call you back】
//let's go.........
}
}
}
1,模板类
package com.pattern.template;
public abstract class CaffeineBeverageWithHook {
void prepareRecipe(){
boilWater();
brew();
pourInCup();
if(customerWantsCondiments()){
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater(){
System.out.println("Boiling water");
}
void pourInCup(){
System.out.println("Pouring into cup");
}
boolean customerWantsCondiments(){
return true;
}
}
package com.pattern.template;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CoffeeWithHook extends CaffeineBeverageWithHook{
/**
* @see com.pattern.template.CaffeineBeverageWithHook#brew()
*/
@Override
void brew() {
System.out.println("Dripping Coffee through filter");
}
/**
* @see com.pattern.template.CaffeineBeverageWithHook#addCondiments()
*/
@Override
void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
public boolean customerWantsCondiments(){
String answer = getUserInput();
if(answer.toLowerCase().startsWith("y")){
return true;
} else{
return false;
}
}
private String getUserInput(){
String answer = null;
System.out.println("Would you like milk and sugar with your coffee (y/n)?");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException e) {
System.out.println("IO Exception!");
}
if(answer == null){
return "no";
}
return answer;
}
}
3,测试类
package com.pattern.template;
public class BeverageTestDrive {
public static void main(String[] args) {
CoffeeWithHook coffeeHook = new CoffeeWithHook();
System.out.println("\nMaking tea...");
coffeeHook.prepareRecipe();
}
}
4,输出结果:
Making tea...
Boiling water
Dripping Coffee through filter
Pouring into cup
Would you like milk and sugar with your coffee (y/n)?
y
Adding Sugar and Milk