个人理解,如有错误,还请大家指出。
你开了一家饮料店,出售茶和咖啡。
一个顾客走进了店里,要了一杯茶。
泡茶需要四个步骤:烧水、泡茶叶、将茶倒入杯中、加一滴柠檬汁
你开始泡茶:
public class Tea {
public void allStepToMakeTea() {
boilWater();
makeTea();
pourIntoCup();
addLemonJuice();
}
public void boilWater() {
System.out.println("boiling water");
}
public void makeTea() {
System.out.println("add tea, add water");
}
public void pourIntoCup() {
System.out.println("pouring into cup");
}
public void addLemonJuice() {
System.out.println("add lemon juice");
}
}
送走了这位顾客,有一位顾客走入店里,要了一杯咖啡。
咖啡的制作步骤:烧水、冲泡咖啡、将咖啡倒入杯中、加一些牛奶。
你开始做咖啡:
public class Coffee{
public void allStepToMakeCoffee(){
boilWater();
makeCoffee();
pourIntoCup();
addMilk();
}
public void boilWater() {
System.out.println("boiling water");
}
public void makeCoffee() {
System.out.println("add coffee, add water");
}
public void pourIntoCup() {
System.out.println("pouring into cup");
}
public void addMilk() {
System.out.println("add milk");
}
}
这时你发现,泡茶和泡咖啡之间存在重复的步骤(体现在代码里,就是存在重复的代码)。
你想到:以后想要修改烧水步骤的话,你要修改很多地方,这很糟糕。因此你想要将共同的部分抽取出来,放在一个基类中。
因此,你写了一个基类,规范了饮料制作的流程:
public abstract class Beverge {
public final void allStepToMakeBeverge() {
boilWater();
make();
pourIntoCup();
addCondiments();
}
public void boilWater() {
System.out.println("boiling water");
}
public abstract void make();
public void pourIntoCup() {
System.out.println("pouring into cup");
}
public abstract void addCondiments();
}
你将allStepToMakeBeverge()方法声明成final,以免以后饮料店的店员不按流程来。
一个顾客点了一杯茶:
public class Tea extends Beverge {
public void make() {
System.out.println("add tea, add water");
}
public void addCondiments() {
System.out.println("add lemon juice");
}
}
一个顾客要了一杯咖啡:
public class Coffee extends Beverge {
public void make() {
System.out.println("add coffee, add water");
}
public void addCondiments() {
System.out.println("add milk");
}
}
你想新研发饮料,只需继承Beverge类,实现make()和addCondiments()方法即可。
好了,不知不觉中,我们用了一个新的设计模式:模板方法。下面我们给它来一个正式的定义:
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
回到上面的例子中,我们可以看到:Beverge类的allStepToMakeBeverge()方法定义了算法(此处是做饮料)的骨架,各个饮料的冲泡步骤和加辅料步骤不同,我们将make()和addCondiments()延迟到子类中实现,我们可以不改变做饮料的流程的情况下,重新定义算法的make()和addCondiments()步骤。
模板方法可以确保算法的结构保持不变,而子类提供部分实现。