默然回首,那人却在灯火阑珊处 - 回调模式
Java线程技术是现实世界的复杂业务场景中的“座上宾”。创建线程的方式我们几乎也是烂熟于心:
- 继承Thread方式;
- 实现Runnable接口方式;
- 线程池方式。
代码1:
public class TestThread {
public static void main(String[] args) {
Thread t = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("我是run()函数");
}
});
t.start();
}
}
下面我们继续“折腾”一下,来个不熟悉的版本,实现了同样的功能,如代码2、代码3。
代码2:
//App实现类
public class App implements Runnable {
//Runnable就是回调接口
//run就是回调函数
@Override
public void run() {
System.out.println("这里是回调函数");
}
//App的执行函数
public void doRun(Thread t){
t.start();
}
}
代码3:
public class TestCallback {
public static void main(String[] args){
//定义App对象引用
App app = new App();
//定义框架对象引用
Thread t = new Thread(app);
//由App函数调用,并传入底层框架对象引用
app.doRun(t);
}
}
看了上述代码,是不是觉得也是很熟悉?
是的!读到这里,很多老铁肯定会联想到上篇文章中提到的回调特征图,我们同样放在了本文的图1。Runnable接口是JDK框架定义的回调接口类;Thread类是JDK框架类库提供的类;App类是用户自定义的类;run方法就是回调函数。完全符合回调机制的特征。
是的!老铁们没有想错,我们常用的Runnable接口创建线程的方式,其实就是利用了回调技术。回调技术不仅用于框架实现,在我们很多业务场景中也会用到,请继续往下看。
【注意】文中提及框架/类库只是为了形象化说明是底层实现;同样地,App也只是为了形象划说明是上层实现。回调技术不仅仅用于框架设计中,其本质上是分层思想,同样适用于我们业务代码的实现。
敌不动我不动 - 观察者模式
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己 —— 观察者模式定义。
后续会有系列文章讲讲常见设计模式的目的、使用场景、实现技术及优缺点介绍,敬请期待!本文的重点主要讲讲观察者模式的实现方式,show me the code —— 见代码4 - 8 。设计模式的类图很简单,见下图。
代码4:
//观察者;实为“定义回调接口”
public interface Observer {
//更新方法;实为“定义回调方法”
public void update();
}
代码5:
//具体观察者
public class ConcreteObserver implements Observer{
//实现更新方法
@Override
public void update() {
System.out.println("我是回调函数!");
}
}
代码6:
import java.util.Vector;
//定义被观察者
public abstract class Subject {
//定义观察者列表
private Vector<Observer> obses = new Vector<Observer>();
//注册观察者:实为“注册回调接口”
public void addObserver(Observer o){
this.obses.add(o);
}
//删除观察者
public void removeObserver(Observer o){
this.obses.remove(o);
}
//通知注册的所有观察者:实为“调用回调接口”
public void notifyObservers(){
for(Observer o : obses){
//调用更新方法:实为“调用回调”
o.update();
}
}
}
代码7:
//具备的被观察者
public class ConcreteSubject extends Subject{
//被观察者的自定义动作
public void userAction(){
super.notifyObservers();
}
}
代码8:
public class TestCase {
public static void main(String[] args){
//创建一个被观察者
ConcreteSubject subject = new ConcreteSubject();
//创建一个观察者
Observer obs = new ConcreteObserver();
//将观察者加入到被观察者中
subject.addObserver(obs);
//被观察者发起动作
subject.userAction();
}
}
老铁们可以自行套用线程例子的方法并结合上述代码中的注释,来识别一下为什么观察者模式也应用了回调技术,并欢迎老铁将思考过程写在留言区与大家共同交流讨论。
更加准确的说法是:观察者模式是“变异”的回调技术。观察者模式中里面被观察者维护了很多的观察者的引用,而回调里面只是维护了一个引用。
划重点
- 回调技术是非常常用且实用的技术,平时在看代码、写代码的时候应结合场景需求恰当利用。
- 回调技术的应用场景包括:关联行为场景;事件多级触发;消息队列处理等等。
转载自公众号:代码荣耀