概述
回调函数就是一个通过函数指针调用的函数。
把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数
注:回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
机制
1)定义一个回调函数
2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者
3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理
意义
- 把调用者与被调用者分开,调用者不关心谁是被调用者
-只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
实现
c 示例
回调函数继承自c语言
typedef int(__stdcall*CompareFunction)(constbyte*,constbyte*)
注:
上述类型就是回调函数的类型,负责用同样的参数形式将参数传递给相应的具体元素比较函数
void DLLDIR__stdcallBubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc);
void DLLDIR__stdcallQuicksort(byte* array,int size,int elem_size,CompareFunction cmpFunc);
注:
使用同样的参数原型的两个排序方法
- ·byte * array:指向元素数组的指针(任意类型)。
- ·int size:数组中元素的个数。
- ·int elem_size:数组中一个元素的大小,以字节为单位。
- ·CompareFunction cmpFunc:带有上述原型的指向回调函数的指针。
bubblesort实现
void DLLDIR__stdcall Bubblesort(byte*array,intsize,intelem_size,cmpFunc)
{
for(inti=0;i<size;i++)
{
for(intj=0;j<size-i-1;j++)
{
//回调比较函数
if(1==(*cmpFunc)(array+j*elem_size,array+(j+1)*elem_size))
{
//两个相比较的元素相交换
byte* temp=newbyte[elem_size];
memcpy(temp,array+j*elem_size,elem_size);
memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);
memcpy(array+(j+1)*elem_size,temp,elem_size);
delete[]temp;
}
}
}
}
回调函数
int__stdcall CompareInts(constbyte*velem1,constbyte*velem2)
{
int elem1=*(int*)velem1;
int elem2=*(int*)velem2;
if(elem1<elem2)
return-1;
if(elem1>elem2)
return1;
return0;
}
int __stdcall CompareStrings(constbyte*velem1,constbyte*velem2)
{
const char* elem1=(char*)velem1;
const char* elem2=(char*)velem2;
return strcmp(elem1,elem2);
}
java 示例
自己调用自己
- 有个学生
Student student = new Student();
- 该学生有写作业这个动作需要执行
student.doHomeWork(someHomeWork);
- 注意到这个写作业这个动作是需要得到入参“作业”的后才能进行的。所以给这个学生new了个简单的题目做。
String aHomeWork = "1+1=?";
student.doHomeWork(aHomeWork);
完整示例
public class Student {
public void doHomeWork(String homeWork) {
System.out.println("作业本");
if("1+1=?".equals(homeWork)) {
System.out.println("作业:"+homeWork+" 答案:"+"2");
} else {
System.out.println("作业:"+homeWork+" 答案:"+"不知道~~");
}
}
public static void main(String[] args) {
Student student = new Student();
String aHomeWork = "1+1=?";
student.doHomeWork(aHomeWork);
}
}
拜托他人调用
- 因为室友帮忙写,所以在doHomeWork动作里面,就不需要有逻辑判断的代码,因为舍友会直接把答案写进来。改成:
student.doHomeWork(aHomeWork, theAnswer);
注:
上句中做作业的动作支持传入“作业”和“答案”,有了这两个,就说明能做好作业了
其中aHomeWork作业是已知的,但是theAnswer这个答案却是室友提供的
- 室友怎么才能提供答案呢,最简单是,室友这个对象直接提供一个传入作业,传出答案的方法,这样该同学就可以直接调用了。
RoomMate roomMate = new RoomMate();
String theAnswer = roomMate.getAnswer(aHomeWork);
student.doHomeWork(aHomeWork, theAnswer);
完整代码
public class RoomMate {
public String getAnswer(String homework) {
if("1+1=?".equals(homework)) {
return "2";
} else {
return null;
}
}
}
public class Student {
public void doHomeWork(String homeWork, String answer) {
System.out.println("作业本");
if(answer != null) {
System.out.println("作业:"+homeWork+" 答案:"+ answer);
} else {
System.out.println("作业:"+homeWork+" 答案:"+ "(空白)");
}
}
public static void main(String[] args) {
Student student = new Student();
String aHomeWork = "1+1=?";
RoomMate roomMate = new RoomMate();
String theAnswer = roomMate.getAnswer(aHomeWork);
student.doHomeWork(aHomeWork, theAnswer);
}
}
开始回调
1.待解决的作业
String aHomeWork = "1+1=?";
2.室友写出答案
String theAnswer = roomMate.getAnswer(aHomeWork);
3.该同学调用,自己把答案写到作业本。(也即是这个步骤不给调用了)
student.doHomeWork(aHomeWork, theAnswer);
4.做作业必须得调用这个方法,而根据需求这个方法必须由室友去调用。那很显然,该室友得保持一个该同学的引用,才能正常调用啊。
即室友说,那你在调用getAnswer方法的时候,除了传入作业,还需要把自己的引用放里面。这样我做完了,直接调用你的做作业方法就行了。
roomMate.getAnswer(aHomeWork,student);
完整代码
public class RoomMate {
public void getAnswer(String homework, Student student) {
if("1+1=?".equals(homework)) {
student.doHomeWork(homework, "2");
} else {
student.doHomeWork(homework, "(空白)");
}
}
}
public class Student {
public void doHomeWork(String homeWork, String answer) {
System.out.println("作业本");
if(answer != null) {
System.out.println("作业:"+homeWork+" 答案:"+ answer);
} else {
System.out.println("作业:"+homeWork+" 答案:"+ "(空白)");
}
}
public static void main(String[] args) {
Student student = new Student();
String aHomeWork = "1+1=?";
RoomMate roomMate = new RoomMate();
roomMate.getAnswer(aHomeWork,student);
}
}
注:在实际开发中,不要将本身全部暴露给其他函数 ,可采用<回调,回调>的方法
public class RoomMate {
public void getAnswer(String homework, DoHomeWork someone) {
if("1+1=?".equals(homework)) {
someone.doHomeWork(homework, "2");
} else {
someone.doHomeWork(homework, "(空白)");
}
}
}
public interface DoHomeWork {
void doHomeWork(String question, String answer);
}
package org.futeng.designpattern.callback.test1;
public class Worker implements DoHomeWork {
@Override
public void doHomeWork(String question, String answer) {
System.out.println("作业本");
if(answer != null) {
System.out.println("作业:"+question+" 答案:"+ answer);
} else {
System.out.println("作业:"+question+" 答案:"+ "(空白)");
}
}
public static void main(String[] args) {
Worker worker = new Worker();
String question = "1+1=?";
new RoomMate().getAnswer(question, worker);
}
}