设计模式----模板设计模式

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


下一篇:js对象中的某属性与对象中的不符