设计模式之模板方法模式(template)

模板方法模式

规范执行流程
提高代码扩展性,复用性
符合开闭原则

案例

ORM框架

mapper接口

public interface RowMapper<T> {

    T mapRow(ResultSet rs,int rowNum) throws Exception;
}

jdbcTemplate


public class JdbcTemplate {

    private DataSource dataSource;

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

    public List<?> executeQuery(String sql,RowMapper<?> rowMapper ,Object[] values){

        try {
            // 获取连接
            Connection conn = this.getConnection();
            // 创建语句集
            PreparedStatement ps = this.createStatement(conn, sql);
            // 执行语句集
            ResultSet rs = this.executeQuery(ps, values);
            // 处理结果集
            List<?> result = this.parseResultSet(rs, rowMapper);
            // 关闭结果集
            this.closeResultSet(rs);
            // 关闭语句集
            this.closeStatement(ps);
            // 关闭连接
            this.closeConnection(conn);

            return result;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


    public List<?> parseResultSet(ResultSet rs, RowMapper<?> rowMapper) throws Exception{

        List<Object> result = new ArrayList<>();
        int rowNum = 1;
        while (rs.next()){
            result.add(rowMapper.mapRow(rs,rowNum++));
        }
        return result;
    }

    public ResultSet executeQuery(PreparedStatement ps, Object[] values) throws Exception{

        for(int i= 0;i<values.length;i++){
            ps.setObject(i,values[i]);
        }
        return ps.executeQuery();
    }

    public PreparedStatement createStatement(Connection conn, String sql) throws Exception{
        return conn.prepareStatement(sql);
    }

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

    public void closeConnection(Connection conn) throws Exception{
        conn.close();
    }

    public void closeStatement(PreparedStatement ps) throws Exception{
        ps.close();
    }

    public void closeResultSet(ResultSet rs) throws Exception {
        rs.close();
    }
}

List<?> result = this.parseResultSet(rs, rowMapper);作为钩子函数

实体类

public class User {

    private String username;

    private String password;

    // get/set ...
}

模板实现类

public class UserDao extends JdbcTemplate{

    public UserDao(DataSource dataSource) {
        super(dataSource);
    }

    public List<?> selectAll(String sql){
        return super.executeQuery(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws Exception {
                User user = new User();
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
                return user;
            }
        },null);
    }
}

Main

public class Main {

    public static void main(String[] args) {
        // 模拟调用
        UserDao userDao = new UserDao(null);
        List<?> users = userDao.selectAll("select * from user");
        System.out.println(users);
    }
}

暴露一个钩子函数可供后续实现类处理不同逻辑,但是主流程可控

应用

AbstractList get()作为钩子函数
HttpServlet service()作为钩子函数


设计模式之模板方法模式(template)
https://www.blaaair.com/archives/she-ji-mo-shi-zhi-mo-ban-fang-fa-mo-shi-template
作者
Glo6f
发布于
2022年04月04日
许可协议