一、定义
Template Design: 模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤
二、应用场景
场景1:某个业务整体流程中,存在固定流程和自定义流程的逻辑,固定流程是不变的,自定义流程是变化的;
场景2: 为框架提供扩展点
三、存在的问题
存在的问题:1. 无法自定义流程,需要修改原有的代码,不符合开闭原则;2. 无法应对未来的变化,扩展性不好
解决的问题:复用和框架扩展问题
四、 具体实现
优缺点:提高了代码的复用性和可扩展性
五、回调函数
**回调函数:**是一种双向调用关系。A将函数F注册到B中,A调用B的P函数时,P函数会反过来调用函数F,函数F就是回调函数。
/**
* 客户端,使用框架回调函数的地方
*/
public class AClass {
public static void main(String[] args) throws InterruptedException {
BClass bClass = new BClass();
bClass.process(() -> {
TimeUnit.SECONDS.sleep(10);
System.out.println("hello A");
});
System.out.println("ahufahug");
}
}
public class BClass {
public void process(Callback callback) throws InterruptedException {
if (!check()) {
return;
}
callback.methodToCallback();
execute();
}
private boolean check() {
return true;
}
private void execute() {
System.out.println("ahufha");
}
}
从上述代码中可知,回调函数就是methodToCallback(),该函数提供了扩展的功能;check和execute函数,是通用的逻辑,由框架默认实现,保证了代码的复用性。
回调函数分为同步回调和异步回调。同步回调指的是调用方会等待回调函数执行完毕后再继续执行后续代码。也就是说,回调函数会阻塞调用方的线程,直到回调函数执行完成。
异步回调:调用方不会等待回调函数执行完毕,而是立即继续执行后续代码。回调函数的执行是在另一个线程或事件循环中进行的,不会阻塞调用方的线程。更类似于观察者模式。
AsyncClass asyncClass = new AsyncClass();
asyncClass.process(() -> {
TimeUnit.SECONDS.sleep(10);
System.out.println("hello Async");
});
System.out.println("end async");
public class AsyncClass {
public void process(AsyncCallback callback) {
// 使用另外一个线程来执行,可以不用等函数执行完后,就可以返回
new Thread(() -> {
try {
callback.asyncCallback();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
六、回调和模板的区别和联系
联系:两者适用的应用场景都是类似的,都保证了代码复用性,提高了代码的扩展性。
区别:
- 回调基于组合关系,是一种对象之间的关系,模板基于继承关系,是一种类之间的关系;
- 回调可以使用匿名内部类来创建回调对象,不需要事先定义类;模板方法需要针对不同的实现定义不同的子类;
- 若某个类中定义了多个模板方法,子类需要实现所有的抽象方法;回调更加灵活,只需要往模板方法中注入回调对象即可