模板方法模式(Template Method)

模板方法模式(Template Method)

概述:

  定义一个操作中的算法的骨架, 而将一些步骤延迟到子类中。 Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  例如生产饮料的流程:加原料、加水、烧水、加工、混合。现在我们向针对加原料来写一些算法,但是不能影响整个流程结构,就可以用到模板方法模式。

使用场景分析:

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

public class JdbcTemplate {

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

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

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

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

	private void closeResultSet(ResultSet rs) throws  Exception{
        rs.close();
    }
    
    private void closeStatement(Statement stmt) throws  Exception{
        stmt.close();
    }

    private void closeConnection(Connection conn) throws  Exception{
        //通常把它放到连接池回收
    }

    private List<?> parseResultSet(ResultSet rs,RowMapper rowMapper) throws  Exception{
        List<Object> result = new ArrayList<Object>();
        int rowNum = 1;
        while (rs.next()){
            result.add(rowMapper.mapRow(rs,rowNum ++));
        }
        return result;
    }

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

            //1、获取连接
            Connection conn = this.getConnection();
            //2、创建语句集
            PreparedStatement pstmt = this.createPreparedStatement(conn,sql);
            //3、执行语句集,并且获得结果集
            ResultSet rs = this.executeQuery(pstmt,values);
            //4、解析语句集
            List<?> result = this.parseResultSet(rs,rowMapper);

            //5、关闭结果集
            this.closeResultSet(rs);
            //6、关闭语句集
            this.closeStatement(pstmt);
            //7、关闭连接
            this.closeConnection(conn);

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

}
public interface RowMapper<T> {

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

}
public class MemberDao {
    //为什么不继承,主要是为了解耦
    private JdbcTemplate JdbcTemplate = new JdbcTemplate(null);

    public List<?> query(){
        String sql = "select * from t_member";
        return JdbcTemplate.executeQuery(sql,new RowMapper<Member>(){
            @Override
            public Member mapRow(ResultSet rs, int rowNum) throws Exception {
                Member member = new Member();
                member.setUsername(rs.getString("username"));
                member.setPassword(rs.getString("password"));
                member.setAge(rs.getInt("age"));
                member.setAddr(rs.getString("addr"));
                return member;
            }
        },null);
    }
}

  上述代码中就是模拟出真实使用JdbcTemplate的场景,我们只需要实现RowMapper接口就可以完成解析ResultSet的实际场景,又可以调用整个Jdbc流程。

策略模式模板模式对比

  • 策略模式:只有选择权(有用户自己选择已有的固定算法)
  • 模板模式:侧重的点不是选择,因为没得选择,你必须这么做,你可以参与某一部分内容自定义。

  设计模式从来都是组合使用,你中有我,我中有你。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值