之前说了控制流中的四种,分别是顺序、分支、循环和递归(递归使用的场合较少,但却是无法替代的),现在就剩下最后一种了,这就是回调。
回调(念diào,不念tiáo)是编程专用术语,这个在其他领域都是没有的。回调的字面意思直接翻译过来就是:「回过头来调用」。
前面也说过,计算机干活有两种模式:同步和异步,拿狗蛋找黑娃的事例举了例子,这里继续拿他俩举例。狗蛋去找二丫问黑娃的电话,二丫说我要找找。但是这时候狗蛋没有「干等」,也没并有自己去问其他人,因为他妈妈打电话给他说有急事要他赶紧回家,临走时告诉二丫说:如果你找到了黑娃的电话,就给打电话告诉我,并且把自己的电话留给她了。
如果整个过程按照时间顺序展开,应该是有这么四个步骤:
这种做事的方式,在计算机编程里面,就叫做「回调」(可以理解为二丫回头调用狗蛋的联系方式通知他查找结果)。
更为通俗的例子是做家务:例如洗衣服。
l 女主人把衣服放到洗衣机里
l 洗衣机洗衣服,女主人去忙其他事情
l 洗衣机洗完衣服,发出通知(滴滴声)
l 女主人听到声音,来取出衣服晾晒
实现代码:
/** * 做家务的接口 * * @author 湘王爱娟娟 */ public interface HouseWork { public void dry(); }
/** * 洗衣机 * * @author 湘王爱娟娟 */ public class WashingMachine { private Vector<HouseWork> vector = new Vector<>(); public void register(HouseWork work) { vector.add(work); } public void unregister(HouseWork work) { vector.remove(work); } public void notifyObserver() { for (HouseWork work : vector) { work.dry(); } } public static void main(String[] args) throws InterruptedException { // 洗衣机 WashingMachine machine = new WashingMachine(); // 女主人 Woman woman = new Woman(); // 洗衣机让女主人成为自己的观察者 machine.register(woman); System.out.println("将衣服放到洗衣机。。。"); System.out.println("买菜、遛娃中。。。"); Thread.sleep(3000); // 通知观察者(女主人),衣服洗完了 machine.notifyObserver(); } }
/** * 女主人(具体做家务的人) * * @author 湘王爱娟娟 */ public class Woman implements HouseWork { @Override public void dry() { System.out.println("可以晾衣服了"); } }
或者,使用更精简的代码来实现这个过程(需安装Java8以上版本):
@FunctionalInterface interface Wash { // 洗衣服 public void finish(); } /** * 女主人 * * @author 湘王爱娟娟 */ public class Hostess { public void washClothes(Wash wash) { // 把衣服丢到洗衣机 try { // 洗衣服 TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } // 衣服洗完了 wash.finish(); } public void dosomething() { System.out.println("洗碗、拖地、遛娃/遛狗中......"); } public static void main(String[] args) { System.out.println("把衣服放到洗衣机,先忙别的"); // 准备把衣服丢到洗衣机 new Thread( // 丢到洗衣机 () -> new Hostess().washClothes( // 洗衣服 () -> System.out.println("嘀~嘀~嘀~.......(衣服洗完了)") ) ).start(); // 女主人去忙别的了 new Hostess().dosomething(); } }
这就是完整的回调过程和示例演示。
对于初次接触回调的人来说,可能会有点绕,不好理解。尤其是回调和异步(《计算机干活的两种方式》中提到的方式)有什么区别?稍微有些基础的人还会问:回调和观察者模式又有什么区别?简单两句话就可以说清楚了:
首先,回调本质上也是一种异步模式。但很明显,狗蛋需要得到结果,而且是从别人那里得到结果;异步关注的则是「别干着等」这件事,有没有结果,相对来说不重要;
其次,观察者模式是一种思维方法,而回调是一种具体实现。在观察者模式中,可以有多个观察者,而回调函数中的「观察者」只有一个。
至于什么是观察者模式,以后会讲。