什么是模板模式呢,我们先看一个早上煮稀饭的流程,煮稀饭的时候第一步就是将水烧开,第二步就是放材料,煮什么稀饭放什么材料,第三步就是等稀饭开锅,第四步是将稀饭盛到碗里,第五步给稀饭里加一点糖,大体流程就是这样吧,我们在想想看,是不是做大部分稀饭都是这样的,没错,那么我们就可以给它总结一个流程:
-
将水烧开
-
放材料
-
等稀饭开锅
-
将稀饭盛到碗里
-
给稀饭里加糖
这个就是做稀饭的流程,如果你每定义一个做稀饭的类,那么你就要把这些代码重复实现一遍,所以我们把这个流程固定化放入到一个抽象类中,做稀饭第一步肯定是烧开水吧,我们就可以把烧开水这个方法固定,同样的,第三步、第四步、第五步固定化,第二步是不是做什么稀饭,放什么材料,那么我们就可以将这个方法抽象化,让它的子类去各自实现就好了。这就是一个简单的模板方法模式,一起实现一下它:
abstract class Porridge{
//我们将这个方法声明为final不希望子类修改它
final void doPorridge(){
boilWater();
putTheMaterial();
waiting();
pull();
sugaring();
}
//做稀饭的第一步烧水
void boilWater(){
System.out.println("1.将水烧开");
}
//做稀饭的第二步放材料,将方法抽象化
abstract void putTheMaterial();
//第三步等锅开
void waiting(){
System.out.println("3.等待锅开");
}
//第四步把稀饭盛到碗里
void pull(){
System.out.println("4.将稀饭盛到碗里");
}
void sugaring(){
System.out.println("5.加糖");
}
}
//我们来做一个绿豆汤
class SweetMungBeanSoup extends Porridge{
//实现第二步
@Override
void putTheMaterial() {
System.out.println("2.放绿豆");
}
}
//再做一个红豆稀饭
class RedBean extends Porridge{
//实现第二步
@Override
void putTheMaterial() {
System.out.println("2.放入红豆和大米");
}
}
public class TestDemo2 {
public static void main(String[] args) {
Porridge porridge = new SweetMungBeanSoup();
porridge.doPorridge();
Porridge porridge1 = new RedBean();
porridge1.doPorridge();
}
}
结果为:
1.将水烧开
2.放绿豆
3.等待锅开
4.将稀饭盛到碗里
5.加糖
1.将水烧开
2.放入红豆和大米
3.等待锅开
4.将稀饭盛到碗里
5.加糖
那么问题来了,有的人喝稀饭不喜欢放糖怎么办?
那么第五步我们就引入一个钩子方法,钩子方法就是我默认不加糖,如果子类想加,那就再加,重新实现一下这个代码:
import java.util.Scanner;
abstract class Porridge{
//我们将这个方法声明为final不希望子类修改它
final void doPorridge(){
boilWater();
putTheMaterial();
waiting();
pull();
if(want()){
sugaring();
}
}
//做稀饭的第一步烧水
void boilWater(){
System.out.println("1.将水烧开");
}
//做稀饭的第二步放材料,将方法抽象化
abstract void putTheMaterial();
//第三步等锅开
void waiting(){
System.out.println("3.等待锅开");
}
//第四步把稀饭盛到碗里
void pull(){
System.out.println("4.将稀饭盛到碗里");
}
void sugaring(){
System.out.println("5.加糖");
}
//钩子方法
boolean want() {
String ret = null;
System.out.println("加糖吗?");
Scanner scanner = new Scanner(System.in);
ret = scanner.nextLine();
if(ret.equals("加") ){
return true ;
}else{
return false;
}
}
}
//我们来做一个绿豆汤
class SweetMungBeanSoup extends Porridge{
//实现第二步
@Override
void putTheMaterial() {
System.out.println("2.放绿豆");
}
}
//再做一个红豆稀饭
class RedBean extends Porridge{
//实现第二步
@Override
void putTheMaterial() {
System.out.println("2.放入红豆和大米");
}
}
public class TestDemo2 {
public static void main(String[] args) {
Porridge porridge = new SweetMungBeanSoup();
porridge.doPorridge();
Porridge porridge1 = new RedBean();
porridge1.doPorridge();
}
}
结果为:
1.将水烧开
2.放绿豆
3.等待锅开
4.将稀饭盛到碗里
加糖吗?
加
5.加糖
1.将水烧开
2.放入红豆和大米
3.等待锅开
4.将稀饭盛到碗里
加糖吗?
不加
模板设计模式就是将算法的骨架定义到一个方法中,而将一些方法延迟到子类中去实现,模板方法可以是子类在不改算法结构的的情况下,重新实现某些步骤。父类专注于算法本身,而由子类提供完整的步骤。