设计模式----模板设计模式
# 设计模式----模板设计模式
## 模板模式概念
* 什么是模板模式
> 模板模式又叫做模板方法模式,它是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现,简单理解:在实际开发中,如果一段相同的代码在项目中多次重复使用,可以将算法封装到一个模板方法中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。
## 模板模式事例
* 用事例代码解释模板模式
> 比如:周末和对象约上去看电影,有如下步骤:网上订票、去电影院、取票、找座位、看电影,以上都是必要的步骤,这里定义一个非必要步骤,是否购买爆米花的步骤;今天想吃爆米花就买,相反就不买。下面就这个例子进行编写事例代码。
1)定义一个抽象类
```java
public abstract class SeeMovie {
/**
* 定义看电影的方法
*/
protected final void see(){
//1、网上订票
this.buyTicket();
//2、去电影院
this.go();
//3、取票
this.takeTicket();
//4、找座位
this.findSeat();
//5、观看电影
this.enjoyMovie();
//6、购买爆米花
this.buyPopcorn();
}
final void buyTicket(){
System.out.println("购买电影票");
}
final void go(){
System.out.println("去电影院");
}
final void takeTicket(){
System.out.println("取电影票");
}
final void findSeat(){
System.out.println("寻找座位");
}
final void enjoyMovie(){
System.out.println("欣赏电影");
}
//购买爆米花,可选方法
abstract void buyPopcorn();
}
```
2)定义张三看电影的类,继承SeeMovie抽象类
```java
public class ZhangSanSeeMovie extends SeeMovie{
//重写钩子方法
@Override
void buyPopcorn() {
System.out.println("看电影当然要吃爆米花,才有灵魂");
}
}
```
3)定义李四看电影的类,继承SeeMovie抽象类
```java
public class LiSiSeeMovie extends SeeMovie{
@Override
void buyPopcorn() {
System.out.println("今天肚子好撑,吃不下爆米花了");
}
}
```
4)测试类
```java
public class SeeMovieTest {
public static void main(String[] args) {
System.out.println("***张三看电影***");
SeeMovie zhangsanSee = new ZhangSanSeeMovie();
zhangsanSee.see();
System.out.println("***张李四看电影***");
SeeMovie lisiSee = new LiSiSeeMovie();
lisiSee.see();
}
}
```
5)测试结果
![image-20210617223912207](https://tx-account-1304038194.cos.ap-chongqing.myqcloud.com/article-image/20210617223915.png)
* 事例代码及结果分析
> 在上述事例中,可以发现,看电影基本是固定的流程,去看电影都需要经历必要的步骤,那么将其抽取成模板类即可,比如上述代码中的SeeMovie抽象类,如果在众多方法中,需要子类可以自定义的方法,可以定义为钩子方法,比如上述事例中的buyPopcorn方法,那么子类可以根据自己的需求进行重写即可。这种就是典型的模板模式。
## 从JDBC中学习模板模式
* 说明
> 以jdbc执行查询为例,原生的jdbc类操作,基本步骤都需要经历,注册驱动、创建连接、发送sql指令、获取结果集和关闭连接的操作,下面就针对原生jdbc的查询为例,学习模板模式
1)定义一个顶层的mapper接口,用于ORM映射
```java
public interface Mapper {
T mapRow(ResultSet rs,int rowNum) throws Exception;
}
```
2)定义JDBC的操作模板,上面已经说明,模板模式最重要的类
```java
public abstract class JdbcTemplate {
//定义数据源
private DataSource dataSource;
//构造方法初始化数据源
public JdbcTemplate(DataSource dataSource){
this.dataSource = dataSource;
}
public List<? > executeQuery(String sql,Mapper mapper,Object[] values){
try {
//1、获取连接
Connection connection = this.getConnection();
//2、创建预编译对象
PreparedStatement ps = this.createPreparedStatement(connection,sql);
//3、执行sql语句,并获取语句集
ResultSet resultSet = this.executeQuery(ps,values);
//4、处理结果集
List<? > result = this.parseResultSet(resultSet,mapper);
//5、关闭结果集
this.closeResultSet(resultSet);
//6、关闭预编译对象
this.closeStatement(ps);
//7、关闭连接
this.closeConnection(connection);
//8、返回结果
return result;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
//创建连接方法
protected Connection getConnection() throws Exception{
return this.dataSource.getConnection();
}
//获取预编译对象方法
protected PreparedStatement createPreparedStatement(Connection connection,String sql) throws Exception {
return connection.prepareStatement(sql);
}
//执行sql语句,并获取结果集的方法,子类只需要重写此方法即可
protected ResultSet executeQuery(PreparedStatement ps,Object[] values) throws Exception{
for(int i = 0;null != values && i < values.length;i++){
ps.setObject(i,values[i]);
}
return ps.executeQuery();
}
//处理结果集的方法
protected List<? > parseResultSet(ResultSet resultSet,Mapper mapper) throws Exception{
List