设计模式----模板设计模式
模板模式概念
- 什么是模板模式
模板模式又叫做模板方法模式,它是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现,简单理解:在实际开发中,如果一段相同的代码在项目中多次重复使用,可以将算法封装到一个模板方法中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。
模板模式事例
- 用事例代码解释模板模式
比如:周末和对象约上去看电影,有如下步骤:网上订票、去电影院、取票、找座位、看电影,以上都是必要的步骤,这里定义一个非必要步骤,是否购买爆米花的步骤;今天想吃爆米花就买,相反就不买。下面就这个例子进行编写事例代码。
1)定义一个抽象类
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抽象类
public class ZhangSanSeeMovie extends SeeMovie{
//重写钩子方法
@Override
void buyPopcorn() {
System.out.println("看电影当然要吃爆米花,才有灵魂");
}
}
3)定义李四看电影的类,继承SeeMovie抽象类
public class LiSiSeeMovie extends SeeMovie{
@Override
void buyPopcorn() {
System.out.println("今天肚子好撑,吃不下爆米花了");
}
}
4)测试类
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)测试结果
- 事例代码及结果分析
在上述事例中,可以发现,看电影基本是固定的流程,去看电影都需要经历必要的步骤,那么将其抽取成模板类即可,比如上述代码中的SeeMovie抽象类,如果在众多方法中,需要子类可以自定义的方法,可以定义为钩子方法,比如上述事例中的buyPopcorn方法,那么子类可以根据自己的需求进行重写即可。这种就是典型的模板模式。
从JDBC中学习模板模式
- 说明
以jdbc执行查询为例,原生的jdbc类操作,基本步骤都需要经历,注册驱动、创建连接、发送sql指令、获取结果集和关闭连接的操作,下面就针对原生jdbc的查询为例,学习模板模式
1)定义一个顶层的mapper接口,用于ORM映射
public interface Mapper<T> {
T mapRow(ResultSet rs,int rowNum) throws Exception;
}
2)定义JDBC的操作模板,上面已经说明,模板模式最重要的类
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<Object> result = new ArrayList<Object>();
//迭代结果集
int rowNum = 1;
while(resultSet.next()){
result.add(mapper.mapRow(resultSet,rowNum++));
}
return result;
}
//关闭结果集方法
protected void closeResultSet(ResultSet resultSet) throws Exception{
if(resultSet != null){
resultSet.close();
}
}
//关闭预编译对象方法
protected void closeStatement(PreparedStatement ps) throws Exception{
if(ps != null){
ps.close();
}
}
//关闭连接方法
protected void closeConnection(Connection connection)throws Exception{
if(connection != null){
connection.close();
}
}
}
3)定义Person类的model,用于后续测试
public class Person {
private int id;
private String name;
private String password;
//为了减少文章篇幅,这里get和set方法及toString方法省略,也可以使用lombok实现
}
4)编写PersonDao实现类,这个类属于JdbcTemplate的子类,需要继承,并重写executeQuery方法
public class PersonDao extends JdbcTemplate{
public PersonDao(DataSource dataSource) {
super(dataSource);
}
//重写父类查询的方法
public List<?> selectAll(){
String sql = "select id,name,password from t_person";
return super.executeQuery(sql,new Mapper<Person>(){
public Person mapRow(ResultSet rs, int rowNum) throws Exception {
//定义实体类
Person person = new Person();
person.setId(rs.getInt("id"));
person.setName(rs.getString("name"));
person.setPassword(rs.getString("password"));
return person;
}
},null);
}
}
5)测试类
public class Test {
public static void main(String[] args) throws Exception{
//这里引入了druid获取数据源dataSource
Properties properties = new Properties();
InputStream in = Test.class.getClassLoader().getResourceAsStream("db.properties");
properties.load(in);
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//执行查询操作
PersonDao personDao = new PersonDao(dataSource);
List<Person> personList = (List<Person>) personDao.selectAll();
//迭代
ListIterator<Person> it = personList.listIterator();
while(it.hasNext()){
Person person = it.next();
System.out.println(person);
}
}
}
6)测试结果
- 总结
在jdbc操作中,从JdbcTemplate模板类中,就可以看出模板模式的核心了,将子类都必须使用的方法,在父类中进行实现执行,如果需要子类执行特定的方法,可以由子类重写即可。比如这个事例中的executeQuery方法。
源码及sql脚本地址:链接:https://pan.baidu.com/s/1goL-TBr22e50Ywsp4pF1fg 提取码:irib
以上就是设计模式中的模板设计模式!!!
关注公众号:源码说