设计模式之模板模式

模板模式又名模板方法模式。
  定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变 一个算法的结构即可重定义该算法的某些特定步骤。 TemplateMethod 模式一般是需要继承的。

和策略模式对比:


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

1. 采用 普通的抽象方法实现

通过Java中得JdbcTemplate例子来解析

1)实体类:

package com.vison.template.dao;
public class Member {
    private String userName;
    private String password;
    private int age;
...get set 方法省略
}

2)JdbcTemplate定义为抽象类,使用模板方法

package com.vison.template;

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

public abstract class JdbcTemplate {

    private DataSource dataSource;

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

    public List<Object> executeQuery(String sql , Object[] values) throws Exception{

        //创建连接
        Connection connection = dataSource.getConnection();
        //创建语句集
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //执行语句集,返回结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //解析结果集
        List<Object> result = new ArrayList<Object>();
        while (resultSet.next()){
            result.add(processResultSet(resultSet));
        }
        //List<?> result = this.processResultSet(resultSet);
        //关闭结果集连接
        resultSet.close();
        //关闭语句集连接
        preparedStatement.close();
        //回收数据库连接
        connection.close();
        //返回结果
        return result;
    }

    //模板方法
    public abstract Object processResultSet(ResultSet rs) throws Exception;
}

3) JdbcTemplate 子类 MemberDAO ,重写模板方法

package com.vison.template.dao;

import com.vison.template.JdbcTemplate;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.util.List;

public class MemberDAO extends JdbcTemplate {

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

    public List<Object> query(String sql, Object[] values)throws Exception{
       return super.executeQuery(sql,values);
    }

	//重写模板方法,可以定义多个子类,来自定义实现这个方法的设置
    @Override
    public Object processResultSet(ResultSet rs) throws Exception {
        Member member = new Member();
        member.setUserName(rs.getString("userName"));
        member.setPassword(rs.getString("password"));
        member.setAge(rs.getInt("age"));
        return member;
    }
}

4) 测试

package com.vison.template;

import com.vison.template.dao.MemberDAO;

import java.util.List;

public class TestJdbcTemplate {

    public static void main(String[] args) throws Exception {

        MemberDAO memberDAO = new MemberDAO(null);
        String sql = "select * from t_user";
        List<Object> result = memberDAO.query(sql, null);
    }
}

2. 采用接口的方式实现

  上面通过继承的方式来实现模板方法的重写,这里可以采用组合的方式;抽象方法可以用接口来实现。
  这种方式采用匿名内部类来实现,就可以减少子类的新建,而且采用组合方式也解耦。优化代码如下

如下:

1) 同样的Member实体类
2) 新建一个接口RowMapper

package com.vison.template.dao;

import java.sql.ResultSet;
import java.util.List;

public interface RowMapper<T> {

   T processResult (ResultSet resultSet) throws Exception;
}

3) JdbcTemplate改写

package com.vison.template;

import com.vison.template.dao.RowMapper;

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;
    }

    //这里传进一个RowMapper接口更灵活使用
    public List<Object> executeQuery(RowMapper rowMapper,String sql , Object[] values) throws Exception{

        //创建连接
        Connection connection = this.getConnection();
        //创建语句集
        PreparedStatement preparedStatement = this.getPreparedStatement(sql, connection);
        //执行语句集,返回结果集
        ResultSet resultSet = this.getResultSet(preparedStatement);
        //解析结果集
        List<Object> result = this.parseResultSet(rowMapper, resultSet);
        //关闭结果集连接
        this.resultSetClose(resultSet);
        //关闭语句集连接
        this.preparedStatementClose(preparedStatement);
        //使用连接池 回收数据库连接
        this.connClose(connection);
        //返回结果
        return result;
    }

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

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

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

    private List<Object> parseResultSet(RowMapper rowMapper, ResultSet resultSet) throws Exception {
        List<Object> result = new ArrayList<Object>();
        while (resultSet.next()){
            result.add(rowMapper.processResult(resultSet));
        }
        return result;
    }

    private ResultSet getResultSet(PreparedStatement preparedStatement) throws SQLException {
        return preparedStatement.executeQuery();
    }

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

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

4) 改写MemberDAO,组合方式

package com.vison.template.dao;

import com.vison.template.JdbcTemplate;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.util.List;

public class MemberDAO  {
    private DataSource dataSource;

    private JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

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

    public List<Object> query(String sql, Object[] values)throws Exception{

        //这里用匿名内部类来实现,就不用每次新建一个模板方法的实现类
       return jdbcTemplate.executeQuery(new RowMapper<Member>() {
           public Member processResult(ResultSet rs) throws Exception {
               Member member = new Member();
               member.setUserName(rs.getString("userName"));
               member.setPassword(rs.getString("password"));
               member.setAge(rs.getInt("age"));
               return member;
           }
       },sql,values);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值