What is the template method?
Template method pattern defines the skeleton of an algorithm in a method and postpones some steps to subclasses. Template method pattern allows subclasses to redefine some steps in the algorithm without changing the overall structure of the algorithm.
public abstract class AbstractClass { public void templateMedhod(){ //A pile of code, general code method1(); //A pile of code, general code method2(); //A pile of code, general code method3(); } protected abstract void method3(); protected abstract void method2(); protected abstract void method1(); }
public class ConcreteClass1 extends AbstractClass { @Override protected void method3() { System.out.println("3"); } @Override protected void method2() { System.out.println("2"); } @Override protected void method1() { System.out.println("1"); } }
public class ConcreteClass2 extends AbstractClass { @Override protected void method3() { System.out.println("3"); } @Override protected void method2() { System.out.println("2"); } @Override protected void method1() { System.out.println("1"); } }
public class client { public static void main(String[] args) { AbstractClass tm = new ConcreteClass1(); tm.templateMedhod(); } }
The pattern is very simple. It is an abstract class that defines methods. It is implemented in the specific implementation class.
There can be one or many specific implementation classes. For example, in the code (ConcreteClass1, ConcreteClass2)
From the code, we can see that templates, methods, patterns, reuse and extension.
We can write the general code in templateMedhod. The differences of each module are implemented separately.
Callback mechanism
In the development process, we often use the callback mechanism.
There are two callback mechanisms: synchronous callback and asynchronous callback.
A calls b, and b calls a in turn, which is a callback.
In c, you can use function pointers. In java, you need to use class objects of callback functions.
Code example:
For example, Zhang San calls Li Si:
Define a callback interface
public interface ICallBack { void methodCallback(); }
Zhang San
public class Zhangsan { public static void main(String[] args) { Zhangsan aClass = new Zhangsan(); aClass.phoneCall(); } public void phoneCall() { System.out.println("find lisi"); Lisi lisi = new Lisi(); System.out.println("Start calling"); lisi.process(new ICallBack() { @Override public void methodCallback() { System.out.println("Zhang San is also connected"); } }); } }
Li Si
public class Lisi { //Used to handle calls public void process(ICallBack callBack){ System.out.println("On the phone..."); System.out.println("Etc. 2 s After planting"); try { Thread.sleep(1000*2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("lisi Answer the phone"); callBack.methodCallback(); } }
The operation result is:
find lisi Start calling On the phone... Etc. 2 s After planting lisi Answer the phone Zhang San is also connected
Synchronous callback refers to executing the callback function before the function returns; Asynchronous callback refers to the execution of the callback function after the function returns.
The above is a synchronous callback function.
Framework example: JDBC template:
jdbc Operating the database is cumbersome. There are many steps.
//1. Create datasource //2. Get connection //3. Create a statement //4 execute sql statement //5 processing resultset //6 close resource object
When we use JDBC template, we can execute the extract method directly. Just perform two steps.
//Get template instance private JdbcTemplate jdbcTemplate=ioc.getBean(JdbcTemplate.class); //Execute sql statement String sql = "select * from Order"; jdbcTemplate.execute(sql);
Other repeated steps are encapsulated into the framework.
Suppose we are designers, and those repeated steps are encapsulated. We can use the template method pattern:
We define an AbstractJdbcTemplate class
public abstract class AbstractJdbcTemplate{ @Autowired private DataSource dataSource; public final Object execute(String sql) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery(sql); //Processing results using template method Object object = handleResultSet(resultSet); return object; } catch (SQLException e) { System.out.print(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { } } if (statement != null) { try { statement.close(); } catch (SQLException e) { } } if (connection != null) { try { connection.close(); } catch (SQLException e) { } } } return null; } protected abstract Object handleResultSet(ResultSet rs) throws SQLException; }
handleResultSet is used to process the ResultSet
For the specific implementation, we use a class to inherit AbstractJdbcTemplate
public class OrderJdbcTemplate extends AbstractJdbcTemplate{ @Override protected Object handleResultSet(ResultSet rs) throws SQLException { List<Order> orders = new ArrayList<Order>(); while (rs.next()) { Order order = new Order(rs.getLong("id"), rs.getString("order_number"), rs.getString("delivery_address")); orders.add(order); } return orders; } }
The result in the ResultSet, and the business object is constructed for return.
Use the jcdbtemplate statement to execute the target code as shown below
AbstractJdbcTemplate jdbcTemplate = new OrderJdbcTemplate(); List<Order> orders = (List<Order>) jdbcTemplate.execute("select * from Order");
If we use the template method pattern, we need to define various implementation classes in the business code, and we need to create and maintain new classes.
This is the disadvantage of the template method pattern, which uses inheritance. We know that when writing code, we try to use interfaces instead of inheritance, that is, programming based on interfaces.
Callback mechanism is based on interface implementation.
Then, we change the handleStatement to an interface.
public interface StatementCallback { Object handleStatement(Statement statement) throws SQLException; }
The original AbstractJdbcTemplate needs to be modified as follows:
public class CallbackJdbcTemplate { @Autowired private DataSource dataSource; public final Object execute(StatementCallback callback){ Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); statement = connection.createStatement(); Object object = callback.handleStatement(statement); return object; } catch (SQLException e) { System.out.print(e); } finally { //Omit exception handling } return null; } }
above
Object object = callback.handleStatement(statement);
The interface is used, which transfers the methods that need subclass abstraction to the StatementCallback.
When we write code, we can use:
public Object queryOrder(final String sql) { CallbackJdbcTemplate jdbcTemplate = new CallbackJdbcTemplate(); return jdbcTemplate.execute(new StatementCallback() { public Object handleStatement(Statement statement) throws SQLException { ResultSet rs = statement.executeQuery(sql); List<Order> orders = new ArrayList<Order>(); while (rs.next()) { Order order = new Order(rs.getLong("id"), rs.getString("order_number"), rs.getString("delivery_address")); orders.add(order); } return orders; } }); }