1. 模板模式
- 兩大作用
- 復(fù)用
- 擴(kuò)展
1.1 示例
- 抽象父類
- 抽象方法
- 需要子類重寫的定義為抽象方法(子類按需重寫方法)
- 不讓子類覆蓋的方法定義為 final
public abstract class Template {
// 模板方法,使用final約束不能輕易修改
public final void execute() {
step1();
step2();
step3();
}
// 抽象方法
abstract void step2();
protected void step1() {
// do something
}
protected void step3() {
// do something
}
}
public class ConcreteTemplate extends Template {
@Override
void step2() {
// do something
}
}
調(diào)用測(cè)試
Template template = new ConcreteTemplate();
template.execute();
1.2 hook
- 鉤子方法,加一個(gè) boolean 方法
public abstract class Template {
public final void execute() {
step1();
if (check()) {
step2();
}
step3();
}
/** 鉤子方法,默認(rèn)不做任何事,子類可以視情況要不要覆蓋 */
boolean check() {
return true;
}
// ... 此處省略其他方法
}
2. 回調(diào)(Callback)
- 回調(diào)是一種雙向調(diào)用關(guān)系
- 模板方法容易繼承泛濫,可以利用回調(diào)函數(shù)代替子類繼承
public interface ICallback {
void before();
void execute();
}
// 此時(shí)不再是抽象類
public final class Template {
public void execute(ICallback callback) {
show();
callback.before();
callback.execute();
}
private void show() {
// do something
}
}
public static void main(String[] args) {
Template template = new Template();
// 往模板方法中注入回調(diào)對(duì)象
template.execute(new ICallback() {
@Override
public void before() {
}
@Override
public void execute() {
}
});
}
2.1 回調(diào)與模板方法的區(qū)別
- 回調(diào)基于組合關(guān)系來(lái)實(shí)現(xiàn),模板模式基于繼承關(guān)系來(lái)實(shí)現(xiàn),回調(diào)比模板模式更加靈活
- 回調(diào)使用匿名類來(lái)創(chuàng)建回調(diào)對(duì)象,可以不用事先定義類;而模板模式針對(duì)不同的實(shí)現(xiàn)都要定義不同的子類
3. 同步回調(diào)與異步回調(diào)
- 同步回調(diào)指在函數(shù)返回之前執(zhí)行回調(diào)函數(shù)
- 異步回調(diào)指的是在函數(shù)返回之后執(zhí)行回調(diào)函數(shù)
3.1 同步回調(diào)
同步回調(diào)類似模板模式
Spring提供了很多Template類,比如JdbcTemplate、RedisTemplate、RestTemplate 都是基于回調(diào)來(lái)實(shí)現(xiàn)的
3.2 異步回調(diào)
例如:事件監(jiān)聽(tīng)器,即傳遞一個(gè)包含回調(diào)函數(shù)(onClick())的對(duì)象給另一個(gè)函數(shù)
public interface ICallback {
void callback(String result);
}
public class Template implements ICallback {
private CallbackResponse response;
public Template(CallbackResponse response) {
this.response = response;
}
public void execute(String request) {
System.out.println("start...");
new Thread(() -> {
// this 很關(guān)鍵
response.handler(this, request);
}).start();
System.out.println("end...");
}
@Override
public void callback(String result) {
System.out.println("異步回調(diào)結(jié)果:" + result);
}
}
public class CallbackResponse {
public void handler(ICallback callback, String request) {
String result = null;
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = request + " ok";
callback.callback(result);
}
}
測(cè)試:
public static void main(String[] args) {
Template template = new Template(new CallbackResponse());
template.execute("request");
}