This article is excerpted from "design patterns should be learned this way"
In the common template method pattern, an abstract method will be designed and given to its subclass implementation. This method is called template method. The hook method is an empty implementation of the abstract method or the method defined in the interface, and it is also an implementation of the template method pattern.
1 hook method in template mode
We take the online course creation process as an example: Publishing preview materials → making courseware PPT → live online broadcast → submitting class notes → submitting source code → arranging homework → checking homework. First create the abastractsource abstract class.
public abstract class AbastractCourse { public final void createCourse(){ //1. Release preview materials postPreResoucse(); //2. Making courseware PPT createPPT(); //3. Live broadcast online liveVideo(); //4. Upload after class materials postResource(); //5. Assignment postHomework(); if(needCheckHomework()){ checkHomework(); } } protected abstract void checkHomework(); //Hook Method protected boolean needCheckHomework(){return false;} protected void postHomework(){ System.out.println("Assign homework"); } protected void postResource(){ System.out.println("Upload after class materials"); } protected void liveVideo(){ System.out.println("Live teaching"); } protected void createPPT(){ System.out.println("Making courseware"); } protected void postPreResoucse(){ System.out.println("Release preview materials"); } } Copy code
There is a hook method in the above code, which may not be understood by some small partners. The author will explain it here. The main purpose of designing hook method is to intervene the execution process, so as to make the control behavior process more flexible and more in line with the actual business needs. The return value of hook methods is generally the return value suitable for conditional branch statements (such as boolean, int, etc.). Partners can decide whether to use the hook method according to their business scenarios. Then create the JavaCourse class.
public class JavaCourse extends AbastractCourse { private boolean needCheckHomework = false; public void setNeedCheckHomework(boolean needCheckHomework) { this.needCheckHomework = needCheckHomework; } @Override protected boolean needCheckHomework() { return this.needCheckHomework; } protected void checkHomework() { System.out.println("inspect Java task"); } } Copy code
Create the python course class.
public class PythonCourse extends AbastractCourse { protected void checkHomework() { System.out.println("inspect Python task"); } } Copy code
Finally, write the client test code.
public static void main(String[] args) { System.out.println("=========Architect course========="); JavaCourse java = new JavaCourse(); java.setNeedCheckHomework(false); java.createCourse(); System.out.println("=========Python curriculum========="); PythonCourse python = new PythonCourse(); python.createCourse(); } Copy code
Through such a case, I believe the partners have a basic impression of the template method mode. In order to deepen our understanding, we will introduce a common business scenario.
2. Reconstruct JDBC business operation using template method pattern
Create a template class JdbcTemplate to encapsulate all JDBC operations. Take a query as an example. The tables in each query are different, and the returned data structure is also different. Different data should be encapsulated into different entity objects. The logic of each entity encapsulation is different, but the processing flow before and after encapsulation is unchanged. Therefore, the template method pattern can be used to design such a business scenario. First, create an interface RowMapper that constrains ORM logic.
/** * ORM Mapping customized interfaces * Created by Tom. */ public interface RowMapper<T> { T mapRow(ResultSet rs,int rowNum) throws Exception; } Copy code
Then create an abstract class JdbcTemplate that encapsulates all processing flows.
public abstract class JdbcTemplate { private DataSource dataSource; public JdbcTemplate(DataSource dataSource) { this.dataSource = dataSource; } public final List<?> executeQuery(String sql,RowMapper<?> rowMapper,Object[] values){ try { //1. Get connection Connection conn = this.getConnection(); //2. Create statement set PreparedStatement pstm = this.createPrepareStatement(conn,sql); //3. Execute statement set ResultSet rs = this.executeQuery(pstm,values); //4. Processing result set List<?> result = this.parseResultSet(rs,rowMapper); //5. Close the result set rs.close(); //6. Close the statement set pstm.close(); //7. Close the connection conn.close(); return result; }catch (Exception e){ e.printStackTrace(); } return null; } private List<?> parseResultSet(ResultSet rs, RowMapper<?> rowMapper) throws Exception { List<Object> result = new ArrayList<Object>(); int rowNum = 0; while (rs.next()){ result.add(rowMapper.mapRow(rs,rowNum++)); } return result; } private ResultSet executeQuery(PreparedStatement pstm, Object[] values) throws SQLException { for (int i = 0; i < values.length; i++) { pstm.setObject(i,values[i]); } return pstm.executeQuery(); } private PreparedStatement createPrepareStatement(Connection conn, String sql) throws SQLException { return conn.prepareStatement(sql); } private Connection getConnection() throws SQLException { return this.dataSource.getConnection(); } } Copy code
Create an entity object Member class.
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; } } Copy code
Create the database operation class MemberDao.
public class MemberDao extends JdbcTemplate { public MemberDao(DataSource dataSource) { super(dataSource); } 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(); //Too many fields, prototype mode member.setUsername(rs.getString("username")); member.setPassword(rs.getString("password")); member.setAge(rs.getInt("age")); member.setAddr(rs.getString("addr")); return member; } },null); } } Copy code
Finally, write the client test code.
public static void main(String[] args) { MemberDao memberDao = new MemberDao(null); List<?> result = memberDao.selectAll(); System.out.println(result); } Copy code
It is hoped that through the business scenario analysis of these two cases, the partners can have a deeper understanding of the template method pattern.