回调函数的定义与应用
回调函数的起源还要从C++说起,让我们先来看看C++中是如何使用回调函数的。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
程序员B要让A调用自己的程序B中的一个方法,于是,他通过A中的接口回调自己B中的方法。
为什么要使用回调函数?
因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。
举例
#include<stdio.h> // 方法指针的格式为:int (*ptr)(char *p) 即:返回值(指针名)(参数列表) typedef int (*CallBackFun)(char *p); // 为回调函数命名,类型命名为 CallBackFun,参数为char *p int Afun(char *p) { // 方法 Afun,格式符合 CallBackFun 的格式,因此可以看作是一个 CallBackFun printf("Afun 回调打印出字符%s!\n", p); return 0; } int Cfun(char *p) { // 方法 Bfun,格式符合 CallBackFun 的格式,因此可以看作是一个 CallBackFun printf("Cfun 回调打印:%s, Nice to meet you!\n", p); return 0; } int call(CallBackFun pCallBack, char *p) { // 执行回调函数,方式一:通过命名方式 printf("call 直接打印出字符%s!\n", p); pCallBack(p); return 0; } // int call2(char *p, int (*ptr)(char *p)) int call2(char *p, int (*ptr)()) { // 执行回调函数,方式二:直接通过方法指针 printf("==============\n", p); (*ptr)(p); } int main() { char *p = "hello"; call(Afun, p); call(Cfun, p); call2(p, Afun); call2(p, Cfun); return 0; } |
Java中回调函数的实现
在C/C++中,要用回调函数,被掉函数需要告诉调用者自己的指针地址,但在JAVA中没有指针,怎么办?我们可以通过接口(interface)来实现定义回调函数。
假设我是程序员A,以下是我的程序a:
public class Caller{ private MyCallInterface mcl; public Caller(){} public setCallfuc(MyCallInterface mc){ this.mc=mc; } public call(){ my.func(); } } |
我还需要定义一个接口,以便程序员B根据我的定义编写程序实现接口。
public interface MyCallInterface{ public void func(); } |
于是,程序员B只需要实现这个接口就能达到回调的目的了,测试主函数:
public static void main(String args[]){ Caller call=new Caller(); call.setCallfuc(new MyCallInterface(){ //定义func方法 public void func(){{ TestObject.testMethod(); } }); call.call(); } |
高级话题——Hibernate 中的回调模式应用
package hibernate.template; import org.hibernate.HibernateException; import org.hibernate.Session; public interface HibernateCallBack { // 回掉接口HibernateCallBack // session 是用于操作数据库的!实现了此接口 对session 操作就能操作数据库! public abstract Object execute(Session session) throws HibernateException; } //下面这个类 其实起到了 框架( 抽象类)的作用 。 package hibernate.template; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class HibernateTemplate { public static Object run(HibernateCallBack callback) throws HibernateException { Session session = null; Transaction tx = null; try { session = new Configuration().configure().buildSessionFactory() .openSession(); tx = session.beginTransaction(); callback.execute(session) // 用于操作数据库! Object result = callback.execute(session); tx.commit(); session.flush(); return result; } catch (HibernateException e) { tx.rollback(); return null; } finally { session.close(); } } |
}
先来测试一下:
package hibernate.text; import hibernate.orm.Person; import hibernate.orm.PersonDaoImpl; public class Text { public static void main(String[] args) { HibernateTemplate.run(new HibernateCallBack() { public Object execute(Session session) throws HibernateException { Person p = new Person(); p.setName("aeeewaaaa"); p.setPassword("zzzzzzzzzzz"); /p.setUid("111111"); session.save(p); return null; } }); } } |