1、什么是模板方法模式?
官方解释:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
设计模式大咖闫宏解释:模板方法模式是类的行为型模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。
个人理解:模板方法模式是基于继承结构的一种行为型模式,模板就是这个模式中的抽象父类,父类的方法中,有一个定义了算法框架(方法执行顺序)的模板方法,这些框架之下的方法由子类去进行实现、重写或直接运用,从而使得相同的算法框架可以有不同的执行结果,也是一种多态思想的体现。
2、模板方法模式UML类图与具体解析:
可以看出,模板方法模式由两部分组成:
(1) 抽象类(AbstractClass):抽象类实现了模板方法,定义了算法的框架,其中的方法可以是具体方法也可以是抽象方法(其中抽象方法称为基本操作,算法的框架称为模板方法)。
(2) 具体子类(ConcreteClass):继承抽象类,实现了抽象类中的抽象方法从而完成子类特定的算法,也可以选择是否重写父类中的具体方法。
3、模板抽象类的实现方法:
模板抽象类的实现方法包括三种,分别为:
(1)抽象方法:由抽象类声明,由具体子类实现。
(2)具体方法:具体方法由抽象类声明并实现,而子类并不实现或置换。
(3)钩子方法:钩子方法是由抽象类声明并实现,子类会选择是否应用或是否加以扩展。钩子方法一般有两种实现方式。第一种方式是由抽象类给出空实现,即像下边一样:
<span style="font-size:14px;background-color: rgb(255, 255, 102);">//定义钩子方法,空实现
public void printQianYan(){};</span>
第二种方式可以这样使用挂钩,让其决定里面的代码是否执行:
<span style="font-size:14px;">//我们也可以这样使用挂钩,让其决定里面的代码是否执行
if(hook()){
//打印前言
printQianYan();
}
@Override
public boolean hook() {
return false;
} </span>
4、模板方法模式实例与代码实现
需求:制作一篇文章的模板,包括开头、中间、结尾三个部分。
分析:文章的模板确定,做一个模板方法,其中依次包括打印开头、打印中间、打印结尾三种方法,这个方法框架是固定的,但是每篇文章的开头、中间、结尾是各不相同的,所以将打印开头、打印中间、打印结尾这三种方法做成抽象方法。
打印模板类:
<span style="font-size:14px;"> //定义打印模板类
public abstract class PrintTemplet {
//定义模板方法,包括了方法的执行顺序
public void print() {
printHead();
printBody();
printBottom();
}
//打印开头
public abstract void printHead();
//打印中间
public abstract void printBody();
//打印结尾
public abstract void printBottom();
}</span>
具体子类1:
<span style="font-size:14px;">//子类
public class PrintDemo1 extends PrintTemplet {
//重写打印开头方法
@Override
public void printHead() {
System.out.println("第一篇文章开头");
}
//重写打印中间方法
@Override
public void printBody() {
System.out.println("第一篇文章中间");
}
//重写打印结尾方法
@Override
public void printBottom() {
System.out.println("第一篇文章结尾");
}
}</span>
具体子类2:
<span style="font-size:14px;">public class PrintDemo2 extends PrintTemplet {
@Override
public void printHead() {
System.out.println("第二篇文章开头");
}
@Override
public void printBody() {
System.out.println("第二篇文章中间");
}
@Override
public void printBottom() {
System.out.println("第二篇文章结尾");
}
}</span>
测试类:
<span style="font-size:14px;">public class PrintTest {
public static void main(String[] args) {
//打印第一篇文章
PrintTemplet pt = new PrintDemo1();
pt.print();
//打印第二篇文章
pt = new PrintDemo2();
pt.print();
}
}</span>
运行结果为:
<span style="font-size:14px;">第一篇文章开头
第一篇文章中间
第一篇文章结尾
第二篇文章开头
第二篇文章中间
第二篇文章结尾</span>
可以看出,不同的子类实现了自己的特定算法,我们知道了,模板模式的关键就是:子类置换了父类的可变部分(即抽象方法),但是仍然依据在父类的框架之下。
5、模板方法模式的优缺点:
优点:
(1)模板方法模式将不变的行为抽提到了父类中,去除了子类中的重复代码。
(2)子类可以自由实现抽象算法中的具体细节,有助于算法的扩展。
(3)模板方法模式运用了多态,又称向上转型,这种结构也被称为“好莱坞法则” ,即“别找我们,,用你的时候我们找你”,通过一个父类调用其子类的操作(而不是相反的子类调用父类),通过对子类的扩展增加新的行为,符合“开闭原则”。
缺点:
(1)每个不同的实现都需要定义一个子类,这会导致类的个数的增加,系统不容易管理。
总结:模板方法模式是由抽象父类定义执行框架,然后由子类去实现方法的具体细节。当某些类的算法中用了相同的算法,造成代码的重复的时候,就可以考虑应用模板方法模式了。