模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern)
定义一个骨架,允许子类为其中一个或者多个步骤提供实现。简而言之,就是使用一个类的方法对流程进行规范,子类对这些方法进行实现,以便于达到流程统一的目的。各个子类的公共行为被提取出来放在公共的父类中,其中的某个流程可以交给子类去自己实现,子类也可以选择不实现,作为父类可以定义一个钩子方法,以此告知父类是否执行父类的实现方法,最典型的一个例子就是JDBCTEMPLATE.下面我会写一个简单课程发布的demo,然后模拟一个jdbctempleate写一个demo。
launch a course
public abstract class AbstractCourse { boolean needPpt; AbstractCourse(boolean needPpt) { this.needPpt = needPpt; }
// the whole process will be controled here final void createCourse() { postPreResource(); liveVideo(); postResource(); postHomework();
// here we judge whether the method that should be exucuted or not if (needPpt()) { createPPT(); } } private boolean needPpt() { return needPpt; } private void postHomework(){ System.out.println("postHomework"); } private void postResource(){ System.out.println("postResource"); } private void liveVideo(){ System.out.println("liveVideo"); } // this is a hook method protected abstract void createPPT(); private void postPreResource(){ System.out.println("postPreResource"); } }
- first, we should have a method to control the whole process
- second,we could have a method to let subclass to implement,we call hook method
- finally,we can give subclass power whether i need implement father class or not
public class Arithmetic extends AbstractCourse { Arithmetic(boolean needPpt) { super(needPpt); } @Override protected void createPPT() { System.out.println("createPPT of Arithmetic"); } } public class JavaCourse extends AbstractCourse { JavaCourse(boolean needPpt) { super(needPpt); } @Override protected void createPPT() { System.out.println("create ppt of java"); } }
To test(we can control whether we need to create a ppt or not dynamically)
public class Test { public static void main(String[] args) { Arithmetic arithmetic=new Arithmetic(true); arithmetic.createCourse(); System.out.println("---------JavaCourse-----------------"); JavaCourse javaCourse=new JavaCourse(false); javaCourse.createCourse(); } }
there is a scene to simulate jdbcTemplate
public abstract class JdbcTemplate { private DataSource dataSource; public JdbcTemplate(DataSource dataSource) { this.dataSource = dataSource; }
// formulate a process public final List<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] values) { try { //simulate get data Connection connection = this.getConnection(); PreparedStatement statement = this.createPrePareStatement(connection, sql); ResultSet resultSet = this.executeQuery(statement, values);
// here could be a hook method List<?> result = this.parseResultSet(resultSet, rowMapper); return result; } catch (Exception e) { e.printStackTrace(); } // get connection return null; } private List<?> parseResultSet(ResultSet resultSet, RowMapper<?> rowMapper) throws Exception { List<Object> result = new ArrayList<Object>(); int rowNum = 1; while (resultSet.next()) { Object o = rowMapper.mapRow(resultSet, rowNum++); result.add(o); } return result; } private ResultSet executeQuery(PreparedStatement statement, Object[] values) throws SQLException { for (int i = 0; i < values.length; i++) { statement.setObject(i, values); } return statement.executeQuery(); } private PreparedStatement createPrePareStatement(Connection connection, String sql) throws SQLException { return connection.prepareStatement(sql); } private Connection getConnection() throws Exception { return this.dataSource.getConnection(); } }
each dao want to query whole data should to implement a interface called RowMapper,in class named JdbcTemplate will cope with the RowMapper you implement
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 () { @Override 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); } }
additional assistant class
public interface RowMapper<T> { T mapRow(ResultSet resultSet,int rowNum) throws Exception; } @Data public class Member { private String username; private String password; private String nickname; private int age; private String addr; }
To test
public class Test { public static void main(String[] args) { MemberDao memberDao=new MemberDao(null); memberDao.selectAll(); } }
How is Template Method used in source of code
java.util.AbstractList#get
apparently,it is an abstract method(hook method),but it is called in the same class, as we mentiond other examples
javax.servlet.http.HttpServlet#doGet(actually,in source of code, it wasn't implemented, so it like a hook method)
org.apache.ibatis.executor.BaseExecutor#doUpdate
Sum up
advantages:
- reusability:makeing the same logical code in the one class
- expansibility:different subclass do different code
disadvatnages:
if we need add a new method,that means we need to add a new method to every subclasses