导读
- 模板模式在是Spring底层被广泛的应用,比如事务管理器的实现,JDBC模板的实现。
- 文章首发于作者的微信公众号【码猿技术专栏】
- 今天就来谈谈「什么是模板模式」、「模板模式的优缺点」、「模板模式的简单演示」、「模板模式在Spring底层的实现」。
什么是模板模式
- 模板模式首先要有一个抽象类,这个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
- 定义:「定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。」
- 比如在造房子一样,
地基
,铺线
,房子户型
都是一样的,由开发商决定,但是在交房之后,室内的装修风格
和场景布置
却是由业主决定,在这个场景中,开发商其实就是一个抽象类,地基,铺线,房子户型都是可以复用的,但是装修却是不可复用的,必须由业主决定,此时的每一个业主的房子就是一个实现的子类。 - 模板方法的实现条件注意:
- 必须是一个抽象类。
- 抽象类有一个模板方法,其中定义了算法骨架。
- 为了防止恶意操作,模板方法必须加上
final
关键词。 - 模板方法中除了复用的代码,其他的关键代码必须是抽象的,子类可以继承实现。
优点
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
缺点
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
简单演示
- 比如游戏的运行需要如下几个步骤:上述的三个步骤可以是模板类的抽象方法,由具体的子类实现,比如足球游戏。
- 初始化游戏
- 开始游戏
- 结束游戏
- 定义模板类,必须是一个抽象类,模板方法必须是
final
修饰。
public abstract class Game {
//抽象方法
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板方法
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
- 定义实现类,足球游戏,继承模板类,实现其中的三个抽象方法
public class Football extends Game {
@Override
void endPlay() {
System.out.println("足球游戏结束......");
}
@Override
void initialize() {
System.out.println("足球游戏初始化中......");
}
@Override
void startPlay() {
System.out.println("足球游侠开始了......");
}
}
public class TemplatePatternDemo {
public static void main(String[] args) {
//创建足球游戏实例
Game game = new Football();
//开始游戏
game.play();
}
}
足球游戏初始化中......
足球游侠开始了......
足球游戏结束......
Spring中的模板模式
- Spring底层对于模板模式的使用有很多处,今天陈某带大家康康事务管理器是如何使用模板模式的。
模板抽象类
AbstractPlatformTransactionManager
是Spring中的模板抽象类
,来看看它的继承关系图: ![](https://gitee.com/chenjiabing666/Blog-file/raw/master/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E6%A8%A1%E6%9D%BF%E6%A8%A1%E5%BC%8F/1.png)
- 实现了
PlatformTransactionManager
接口,重载了接口中的方法。
模板方法
- 事务管理器中抽象类中的模板方法不止一个,比如以下两个方法
//提交事务
public final void commit()
//获取TransactionStatus
public final TransactionStatus getTransaction()
- 这两个方法都对于自己要实现的逻辑搭建了一个骨架,主要的功能是由抽象方法完成,由子类来完成。
抽象方法
- 事务管理器抽象类中的抽象方法定义了多个,分别用于处理不同的业务逻辑,由子类实现其中具体的逻辑,如下:
//提交事务
protected abstract void doCommit(DefaultTransactionStatus status);
//回滚事务
protected abstract void doRollback(DefaultTransactionStatus status);
//开始事务
protected abstract void doBegin(Object transaction, TransactionDefinition definition)
//获取当前的事务对象
protected abstract Object doGetTransaction()
- 抽象方法的定义便于子类去扩展,在保证算法逻辑不变的情况下,子类能够定制自己的实现。
具体子类
- 事务管理器的模板类有很多的具体子类,如下图:
-
![](https://gitee.com/chenjiabing666/Blog-file/raw/master/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E6%A8%A1%E6%9D%BF%E6%A8%A1%E5%BC%8F/2.png)
- 其中我们熟悉的有
DataSourceTransactionManager
、JtaTransactionManager
、RabbitTransactionManager
。具体承担什么样的角色和责任不是本节的重点,不再细说。
总结
- 模板模式是一个很重要,易扩展的模式,提高了代码复用性,在Spring中有着广泛的应用,比如
JDBCTemplate
,AbstractPlatformTransactionManager
,这些实现都用到了模板模式。 - 如果觉得陈某的文章能够对你有所帮助,有所启发,关注分享一波,点个在看,谢谢支持!!!