介绍
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
类图说明
今天改用visio 2013来画这个类图,样式看起来和之前的会所有不太一样,添加了各种背景色,看起来更酷炫些。之前是用ProcessOn画的。
从类图中,我们可以看到我们是定义了一个Car的抽象模板类,这个类中定义了四个方法,其中三个方法start(),run(),stop()为抽象方法,需要子类去实现,drive()为模板方法,不需要具体子类实现的。分别定义了BMW和Benz两个子类,去实现具体start,run,stop方法,不同种类的车这三种方法不一样,自行实现,但drive方法是一样的,所以放在父类定义即可,然后client去调drive方法即可,这就是模板方法。
代码示例
文件结构如下:
代码示例:
public abstract class Car {
public abstract void start();
public abstract void run();
public abstract void stop();
// 定义一个驾驶的公共模板方法,自动驾驶
public void drive(){
// 启动汽车
start();
// 跑起来
run();
// 停车
stop();
}
}
public class Benz extends Car {
@Override
public void start() {
System.out.println("奔驰车启动起来了");
}
@Override
public void run() {
System.out.println("奔驰车跑起来了");
}
@Override
public void stop() {
System.out.println("奔驰车已停车");
}
}
public class BMW extends Car {
@Override
public void start() {
System.out.println("宝马车启动起来了");
}
@Override
public void run() {
System.out.println("宝马车跑起来了");
}
@Override
public void stop() {
System.out.println("宝马车已停车");
}
}
public class TemplatePattern {
public static void main(String[] args){
Benz benz = new Benz();
benz.drive();
BMW bmw = new BMW();
bmw.drive();
}
}
运行结果如下:
应用场景
- 有多个子类共有的方法,且逻辑相同
- 重要的、复杂的方法,可以考虑作为模板方法
这里提一句,实际应用中不需要刻意去想着如何使用模板方法,其实只要你发现应用的时候有重复的或者大量子类都copy了同一个方法,那么这个时候就可以将它抽出来了,那么很大可能性就是模板方法了。
为防止恶意操作,一般模板方法都加上 final 关键词
优缺点
优点
- 封装不变部分,扩展可变部分
- 提取公共代码,便于维护
- 行为由父类控制,子类实现
缺点
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
拓展
可以考虑在模板方法中加一个开关控制,然后将这个开关开放给子类来进行控制,子类通过控制开关,达到父类模板方法响应不一样的结果。
如示例中可以加一个是否run的开关,模板方法中判断开则run,关则不run,子类实现父类后,通过重写这个开关告诉父类是开还是关即可达到影响父类的实际行为。