概念
它定义了一个操作算法的框架,将一些步骤延迟到子类中执行。使得子类可以不改变一 个算法的结构即可重定义该算法的某些步骤。还可以通过子类来决定父类算法中某个步骤是 否执行,实现子类对父类的反向控制。 比如启动线程 start 的行为由 JVM 虚拟机来决定,但是该线程做什么事情就不由它来 决定了。对外提供了 run 方法,内部就是你自己线程的执行逻辑。
分析
如果按照模板方法的思路去构建,我们需要剥离出两个角色:(Thread.start()就是一个典型的模板方法模式,以及run方法就是钩子函数)
1. 模板方法:父类,定义一系列方法,提供骨架;
2. 具体类:实现模板方法类提供的骨架。根据自己的个性化需求重写模板方法。
A:定义模板方法类
public abstract class Cook {
abstract void oil();
abstract void egg();
abstract void tomato();
//封装具体行为 : 做饭
public final void cook(){
this.oil();
this.egg();
this.tomato();
}
}
B:定义具体类(我和大厨)
public class Me extends Cook {
@Override
void oil() {
System.out.println("自己:油到多了");
}
@Override
void egg() {
System.out.println("自己:鸡蛋放多了");
}
@Override
void tomato() {
System.out.println("自己:西红柿放多了");
}
}
public class Chef extends Cook {
@Override
void oil() {
System.out.println("大厨:油使用适量");
}
@Override
void egg() {
System.out.println("大厨:鸡蛋使用适量");
}
@Override
void tomato() {
System.out.println("大厨:西红柿使用适量");
}
}
C:测试执行
public class TestCook {
public static void main(String[] args) {
new Me().cook();
new Chef().cook();
}
}
结果:
自己:油到多了
自己:鸡蛋放多了
自己:西红柿放多了
大厨:油使用适量
大厨:鸡蛋使用适量
大厨:西红柿使用适量
钩子函数
实现子 类对父类的反向控制。这个功能我们可以通过钩子函数来实现。 钩子就是给子类一个授权,让子类来决定模板方法的逻辑执行。
A:定义模板方法类
public abstract class Cook {
//钩子函数:子类可以复写,让子类决定是否加油,默认加油
boolean isAddOil(){
return true;
}
abstract void oil();
abstract void egg();
abstract void tomato();
//封装具体行为 : 做饭
public final void cook(){
// 如果子类决定添加,则执行添加油的方法
if (this.isAddOil()){
this.oil();
}
this.egg();
this.tomato();
}
}
B:具体类
public class Me extends Cook {
private boolean isAddOilFlag = true; //是否加油标记,默认加油
public Me(boolean isAddOilFlag) {
this.isAddOilFlag = isAddOilFlag;
}
public Me() {
}
public boolean isAddOilFlag() {
return isAddOilFlag;
}
public void setAddOilFlag(boolean addOilFlag) {
isAddOilFlag = addOilFlag;
}
//不去加油
@Override
boolean isAddOil() {
return isAddOilFlag;
}
@Override
void oil() {
System.out.println("自己:油到多了");
}
@Override
void egg() {
System.out.println("自己:鸡蛋放多了");
}
@Override
void tomato() {
System.out.println("自己:西红柿放多了");
}
}
C:测试
public class TestCook {
public static void main(String[] args) {
Me me = new Me();
me.setAddOilFlag(false); //不放油
me.cook();
new Chef().cook();
}
}
结果:
自己:鸡蛋放多了
自己:西红柿放多了