模板方法模式介绍:

简单介绍

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变
一个算法的结构即可重定义该算法的某些特定步骤。
Template Method 模式一般是需要继承的。这里想要探讨另一种对 Template Method 的理解。Spring
中的 JdbcTemplate,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用
到 JdbcTemplate 已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出
来作为一个参数传入 JdbcTemplate 的方法中。但是变化的东西是一段代码,而且这段代码会用到
JdbcTemplate 中的变量。怎么办?那我们就用回调对象吧。在这个回调对象中定义一个操纵
JdbcTemplate 中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入
这个回调对象到 JdbcTemplate,从而完成了调用。这就是 Template Method 不需要继承的另一种实
现方式。

归类:行为型模式

特点:执行流程固定,但中间有些步骤有细微差别(运行时才确定)。可实现批量生产。

举例:Spring ORM数据模型,JdbcTemplate

示例代码:

JdbcTemplate:

package com.debuggg.test1.templatemethod2;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class JdbcTemplate {

private DataSource dataSource;

public JdbcTemplate(DataSource dataSource){
this.dataSource = dataSource;
}

private Connection getConnection() throws SQLException {
return this.dataSource.getConnection();
}

private PreparedStatement getPreparedStatement(Connection connection, String sql) throws SQLException {
return connection.prepareStatement(sql);
}

private ResultSet getResultSet(PreparedStatement preparedStatement, Object[] values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i, values[i]);
}
return preparedStatement.executeQuery();
}

private List<Object> pareseResultSet(ResultSet resultSet, RowMapper rowMapper) throws Exception {
ArrayList<Object> list = new ArrayList<>();
int num = 1;
while (resultSet.next()){
list.add(rowMapper.mapRow(resultSet,num++));
}
return list;
}

private void closeResultSet(ResultSet resultSet) throws SQLException {
resultSet.close();
}

private void closePreparedStatement(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.close();
}

private void closeConnection(Connection connection) throws SQLException {
connection.close();
}

public List<Object> executeQuery(String sql, Object[] values, RowMapper rowMapper) throws Exception {
//创建连接
Connection connection = this.getConnection();
//创建语句集
PreparedStatement preparedStatement = this.getPreparedStatement(connection, sql);
//得到结果集
ResultSet resultSet = this.getResultSet(preparedStatement, values);
//解析结果集
List<Object> objects = this.pareseResultSet(resultSet, rowMapper);
//关闭结果集
this.closeResultSet(resultSet);
//关闭语句集
this.closePreparedStatement(preparedStatement);
//关闭连接
this.closeConnection(connection);
return objects;
}
}

RowMapper:

package com.debuggg.test1.templatemethod2;

import java.sql.ResultSet;

public interface RowMapper<T> {
T mapRow(ResultSet rs, int rowNum) throws Exception;
}

测试:
User

package com.debuggg.test1.templatemethod2.entity;

public class User {

private String username;
private String password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

dao层代码:

package com.debuggg.test1.templatemethod2.dao;

import com.debuggg.test1.templatemethod2.JdbcTemplate;
import com.debuggg.test1.templatemethod2.entity.User;

import java.util.List;

public class UserDao {

private JdbcTemplate jdbcTemplate = new JdbcTemplate(null);

public List<Object> query() throws Exception {
String sql = "select * from t_user";
return this.jdbcTemplate.executeQuery(sql,null,(resultSet,rowNum) -> {
User user = new User();
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
return user;
});
}

}