回调函数

http://blog.csdn.net/zhuwentao2150/article/details/51006347

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

 

看上去不是那么容易理解,我们来看个例子(知乎):

 

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

这样好理解多了吧,当店员被创建出来的时候,并不知道有谁会来商店里买东西,店员需要和很多不同的对象打交道,需要适配不同类型的对象,这个时候就需要回调函数了。

我们通过一个事例来理解一下回调函数的运用场景:

Me需要完成一个任务,计算1+1=?
Me如果要自己完成这个任务

代码如下
  1. public class Me{  
  2.       
  3.     public void getAnswer(String ques){  
  4.         if(ques.equals("1+1=?")){  
  5.             System.out.println("问题:" + ques + "答案:" + 2);  
  6.         }else{  
  7.             System.out.println("问题:" + ques + "答案:" + "额...");  
  8.         }  
  9.     }  
  10.       
  11.     public static void main(String[] args) {  
  12.         Me m = new Me();  
  13.           
  14.         String ques = "1+1=?";  
  15.         m.getAnswer(ques);  
  16.     }  
  17.   
  18. }  
public class Me{
	
	public void getAnswer(String ques){
		if(ques.equals("1+1=?")){
			System.out.println("问题:" + ques + "答案:" + 2);
		}else{
			System.out.println("问题:" + ques + "答案:" + "额...");
		}
	}
	
	public static void main(String[] args) {
		Me m = new Me();
		
		String ques = "1+1=?";
		m.getAnswer(ques);
	}

}


执行结果
问题:1+1=?答案:2

这个时候问题的处理逻辑都是在Me类中的
如果Me不想自己做,想要找个人帮他完成这个任务时该怎么办呢

代码如下
  1. public class Me{  
  2.       
  3.     public void getAnswer(String ques, String answer){  
  4.         if(answer != null){  
  5.             System.out.println("问题:" + ques + "答案:" + answer);  
  6.         }  
  7.     }  
  8.       
  9.     public static void main(String[] args) {  
  10.         Me m = new Me();  
  11.         HelpPerson hp = new HelpPerson();  
  12.           
  13.         String ques = "1+1=?";  
  14.         String answer = hp.getAnswer(ques);  
  15.         m.getAnswer(ques, answer);  
  16.     }  
  17.   
  18. }  
public class Me{
	
	public void getAnswer(String ques, String answer){
		if(answer != null){
			System.out.println("问题:" + ques + "答案:" + answer);
		}
	}
	
	public static void main(String[] args) {
		Me m = new Me();
		HelpPerson hp = new HelpPerson();
		
		String ques = "1+1=?";
		String answer = hp.getAnswer(ques);
		m.getAnswer(ques, answer);
	}

}
帮助他的HelpPerson
  1. public class HelpPerson {  
  2.       
  3.     public String getAnswer(String ques){  
  4.         if(ques.equals("1+1=?")){  
  5.             return "2";  
  6.         }else{  
  7.             return "额...";  
  8.         }  
  9.     }  
  10. }  
public class HelpPerson {
	
	public String getAnswer(String ques){
		if(ques.equals("1+1=?")){
			return "2";
		}else{
			return "额...";
		}
	}
}

执行结果
问题:1+1=?答案:2

到目前为止我们还没有运用到回调方法,那么哪种情况下需要运用到回调方法呢?
发现了上面的代码问题吗?帮助Me的HelpPerson只提供出了答案,但最终还是要在Me中调用自己的方法才能提交(显示)出来。
那么如何避免这样的现象,让Me更轻松呢
可以让HelpPerson帮忙调用Me中的getAnswer方法

代码如下
  1. public class Me{  
  2.       
  3.     public void getAnswer(String ques, String answer){  
  4.         if(answer != null){  
  5.             System.out.println("问题:" + ques + "答案:" + answer);  
  6.         }  
  7.     }  
  8.       
  9.     public static void main(String[] args) {  
  10.         Me m = new Me();  
  11.         HelpPerson hp = new HelpPerson();  
  12.           
  13.         String ques = "1+1=?";  
  14.         hp.getAnswer(ques, m);  
  15.     }  
  16.   
  17. }  
public class Me{
	
	public void getAnswer(String ques, String answer){
		if(answer != null){
			System.out.println("问题:" + ques + "答案:" + answer);
		}
	}
	
	public static void main(String[] args) {
		Me m = new Me();
		HelpPerson hp = new HelpPerson();
		
		String ques = "1+1=?";
		hp.getAnswer(ques, m);
	}

}
  1. public class HelpPerson {  
  2.       
  3.     public void getAnswer(String ques, Me m){  
  4.         if(ques.equals("1+1=?")){  
  5.             m.getAnswer(ques, "2");  
  6.         }else{  
  7.             m.getAnswer(ques, "额...");  
  8.         }  
  9.     }  
  10. }  
public class HelpPerson {
	
	public void getAnswer(String ques, Me m){
		if(ques.equals("1+1=?")){
			m.getAnswer(ques, "2");
		}else{
			m.getAnswer(ques, "额...");
		}
	}
}

执行结果
问题:1+1=?答案:2

Me调用了HelpPerson中帮忙完成任务的方法,并且传递了一个自己的引用过去,HelpPerson帮忙得到答案后顺便调用了Me方法里的提交(显示)方法,最终完成了任务
这就是简单的回调了

需要注意的是,在调用方法的时候传递自己的引用过去是十分不妥的
实际开发中也不应该出现这样的代码
还有就是传入的一个具体的引用,那么HelpPerson就只能给Me提供服务了,如果其它对象也需要同样的请求怎么办?总不可能又再建一个方法,改变一下引用吧?
这时候我们就需要用到接口了

建立一个接口,规定需要什么东西才能完成任务,比如这里就需要问题,和答案
代码如下
  1. public interface DoQuesAnswerImp {  
  2.     void getQuesAnswer(String ques, String answer);  
  3. }  
public interface DoQuesAnswerImp {
	void getQuesAnswer(String ques, String answer);
}
修改HelpPerson中的引用
  1. public class HelpPerson {  
  2.       
  3.     public void getAnswer(String ques, DoQuesAnswerImp dqai){  
  4.         if(ques.equals("1+1=?")){  
  5.             dqai.getQuesAnswer(ques, "2");  
  6.         }else{  
  7.             dqai.getQuesAnswer(ques, "额...");  
  8.         }  
  9.     }  
  10. }  
public class HelpPerson {
	
	public void getAnswer(String ques, DoQuesAnswerImp dqai){
		if(ques.equals("1+1=?")){
			dqai.getQuesAnswer(ques, "2");
		}else{
			dqai.getQuesAnswer(ques, "额...");
		}
	}
}
  1. public class Me implements DoQuesAnswerImp{  
  2.       
  3.     @Override  
  4.     public void getQuesAnswer(String ques, String answer) {  
  5.         if(answer != null){  
  6.             System.out.println("问题:" + ques + "答案:" + answer);  
  7.         }  
  8.     }  
  9.       
  10.     public static void main(String[] args) {  
  11.         Me m = new Me();  
  12.         HelpPerson hp = new HelpPerson();  
  13.           
  14.         String ques = "1+1=?";  
  15.         hp.getAnswer(ques, m);  
  16.     }  
  17. }  
public class Me implements DoQuesAnswerImp{
	
	@Override
	public void getQuesAnswer(String ques, String answer) {
		if(answer != null){
			System.out.println("问题:" + ques + "答案:" + answer);
		}
	}
	
	public static void main(String[] args) {
		Me m = new Me();
		HelpPerson hp = new HelpPerson();
		
		String ques = "1+1=?";
		hp.getAnswer(ques, m);
	}
}
执行结果
问题:1+1=?答案:2

这样,HelpPerson中的getAnswer方法不用传入具体的引用了
只要是实现了DoQuesAnswerImp接口的对象都可以调用HelpPerson中的getAnswer方法了
是不是非常的方便呢
posted @ 2018-03-05 10:42  旋羽  阅读(294)  评论(0编辑  收藏  举报