定义
Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
通过定义可知,模板方法模式的作用为在不改变模板结构的前提下在子类中重新定义模板中的内容。注意,模板方法模式是基于”继承“的。
UML图
模板方法模式的结构十分简单,由抽象模板和具体模板构成,子类通过重写父类中的抽象方法使得在不改变模板结构的前提下重新定义其表达。
1.抽象模板AbstractClass,其中的方法分为两类:
1. 基本方法:
基本方法也叫做基本操作,是由子类实现的方法,并在模板方法被调用。
2. 模板方法:
一般是一个具体方法,实现对基本方法的调度。一般模板方法都加上final关键字,其不允许被重写。
2.具体模板ConcreteClass:
实现父类所定义的一个或多个抽象方法(基本方法)。
代码:
冲奶粉和冲咖啡的步骤一致,只有一些细节不同。
1.创建抽象类
public abstract class MakeDrink{
//模板
final void process() {
boilWater();
brew();
pourInCup();
addSugar();
}
abstract void brew();
abstract void addSugar();
void boilWater() {
System.out.println("boilWater");
}
void pourInCup() {
System.out.println("pourInCup");
}
}
2.创建子类
public class Milk extends MakeDrink{
@Override
void brew() {
System.out.println("Milk.brew");
}
@Override
void addSugar() {
System.out.println("Milk.addSugar");
}
}
public class Coffee extends MakeDrink{
@Override
void brew() {
System.out.println("Coffee.brew");
}
@Override
void addSugar() {
System.out.println("Coffee.addSugar");
}
}
3.测试
public class Test{
public static void main(String[] args) {
MakeDrink makeDrink = new Coffee();
makeDrink.process();
System.out.println();
makeDrink = new Milk();
makeDrink.process();
}
}
上述代码中,我们将相同部分的代码放在抽象的父类中,将不同的代码放入不同的子类中,子类在不改变父类模板的前提下通过重写特定的方法扩展了父类不同的行为,提高了代码复用性,父类中的模板方法需要使用final关键字,防止被恶意重写。
总结
1.优点
- 提高代码复用性 将相同部分的代码放在抽象的父类中提高了拓展性 。
- 在不改变父类模板结构下对子类扩展从而增加新的行为,实现了反向控制,符合开闭原则。
2.缺点
- 每一个不同的实现都需要一个子类来实现,导致子类的个数增加,使系统膨胀。
3.使用场景
- 多个子类有共有的方法,并且逻辑基本相同时。
- 重要且复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。