模板模式
模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤,属于行为性设计模式。模板方法适用于以下应用场景:
1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。
优点:
利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
把不变的行为写在父类上(抽取共性的过程),去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。
缺点:
1、类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
2、类数量的增加,间接地增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。
举例子老师上课已经形成了一个流程,这时候就可以定义为一个模板
首先创建课程的抽像类
package course; /** * 课程类,就是一个模板 */ public abstract class Course { protected final void createCourse(){ this.yuxi(); this.shangke(); this.send(); if(needHomework()){ check(); } } //定义的方法形成了一套上课的流程 final void yuxi(){ System.out.println("预习资料"); } final void shangke(){ System.out.println("开始上课"); } final void send(){ System.out.println("发送上课资料"); } //抽象方法检查作业,可有可无,只有布置作业才会检查 abstract void check(); //进行判断是否留了作业,微妙变化的控制 protected boolean needHomework(){ return false; } }
然后创建两门课程大数据和java
package course; public class BigData extends Course { //看类图关系的快捷键 ctrl+alt+shift+u @Override void check() { System.out.println("检查大数据的作业"); } }
package course; public class JavaCourse extends Course { private boolean flag=false; public JavaCourse(boolean flag) { this.flag=flag; } @Override void check() { System.out.println("检查java课后作业"); } protected boolean needHomeWork(){ return this.flag; } }
测试类
package course; public class Test { public static void main(String[] args) { Course c=new JavaCourse(false); c.createCourse(); Course c1=new BigData(); c1.createCourse(); } }
再结合第二个案例,数据库连接的模板来看一下,用的是maven项目,里面引入依赖如下
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency>
首先创建一个接口
package JDBC; import java.sql.ResultSet; public interface RowMapper<T> { //定义为泛型 T mapRow(ResultSet rs,int rowNum)throws Exception; }
定义一个实体类
package JDBC; /** * 实体类 */ public class Member { private String username; private String password; private String nickname; private int age; private String addr; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } }
定义模板
package JDBC; 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<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] values){ try { //1、获取连接 Connection conn = this.getConnection(); //2、创建语句集 PreparedStatement pstm = this.createPrepareStatement(conn,sql); //3、执行语句集 ResultSet rs = this.executeQuery(pstm,values); //4、处理结果集 List<?> result = this.paresResultSet(rs,rowMapper); //5、关闭结果集 this.closeResultSet(rs); //6、关闭语句集 this.closeStatement(pstm); //7、关闭连接 this.closeConnection(conn); return result; }catch (Exception e){ e.printStackTrace(); } return null; } protected void closeConnection(Connection conn) throws Exception { //数据库连接池,我们不是关闭 conn.close(); } protected void closeStatement(PreparedStatement pstm) throws Exception { pstm.close(); } protected void closeResultSet(ResultSet rs) throws Exception { rs.close(); } protected List<?> paresResultSet(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; } protected ResultSet executeQuery(PreparedStatement pstm, Object[] values) throws Exception { for (int i = 0; i < values.length; i++) { pstm.setObject(i,values[i]); } return pstm.executeQuery(); } protected PreparedStatement createPrepareStatement(Connection conn, String sql) throws Exception { return conn.prepareStatement(sql); } public Connection getConnection() throws Exception { return this.dataSource.getConnection(); } }
因为连接的步骤差不多,可以直接继承模板
package JDBC; import javax.sql.DataSource; import java.sql.ResultSet; import java.util.List; public class MemberDao extends JdbcTemplate{ public MemberDao(DataSource dataSource) { super(dataSource); } //模拟从数据库获取数据 //mybatis里面的大致封装连接数据库就是这样做的 public List<?> selectAll(){ String sql = "select * from t_member"; return super.executeQuery(sql, new RowMapper<Member>() { 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); } }
测试类
package JDBC; import java.util.List; public class Test { public static void main(String[] args) { MemberDao memberDao=new MemberDao(null); List<?>result=memberDao.selectAll(); System.out.println(result); } }