定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
核心要素:
1、父类抽象类中定义一个模板方法,里面定义了算法(比如调用了多个方法)。
2、子类继承父类并实现父类中的抽象方法,重新定义了算法中的步骤。
举例:
以人为例,每个人的一天基本上都是一样的,起床、吃饭。。。睡觉等。但是具体细节又是不一样的,比如吃的东西不一样,上班收入不一样等。
下面以穷人和富人的一天来详细了解模板方法模式:
1、定义抽象类父类Man
public abstract class Man {
//这是模板方法,声明为final,以免子类改变这个算法的顺序
final void oneDay() {
//定义了算法的骨架,一系列步骤
getUp();
eatBreakfast();
goToWork();
getMoney();
if(!overTimeWork()) {
sleep();
}
}
//抽象出子类共同的地方
void getUp() {
System.out.println("getting up");
}
//不同的地方定义成抽象方法,由子类自己来实现
abstract void eatBreakfast();
abstract void goToWork();
abstract void getMoney();
void sleep() {
System.out.println("go to bed");
}
//钩子方法
boolean overTimeWork() {
return false;
}
}
2、定义子类RichMan
public class RichMan extends Man {
//实现父类中的所有抽象方法,重新定义了模板方法中的算法中的某些步骤
@Override
public void eatBreakfast() {
System.out.println("7点半起床,保姆提前做好了,直接吃");
}
@Override
public void goToWork() {
System.out.println("8点出门,by car,8点半到单位");
}
@Override
public void getMoney() {
System.out.println("make 100000");
}
}
3、定义子类PoorMan
public class PoorMan extends Man {
@Override
public void eatBreakfast() {
System.out.println("6点起床做饭,7点开始吃");
}
@Override
public void goToWork() {
System.out.println("7点半出门,bicycle,8点半到单位");
}
@Override
public void getMoney() {
System.out.println("make 100");
}
@Override
boolean overTimeWork() {
return true;
}
}
大致类图如下:
4、编写测试类Action:
public class Action {
public static void main(String[] args) {
Man richMan = new RichMan();
Man poorMan = new PoorMan();
richMan.oneDay();
System.out.println("====");
poorMan.oneDay();
}
}
5、 结果如下:
拓展点:
父类中有一个名为overTimeWork()的方法,我们称之为钩子。钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。