Spring中模板模式和回调模式(一)
来源:互联网 发布:java工程项目log4j2 编辑:程序博客网 时间:2024/05/22 15:11
模板模式
public abstract class TemplatePattern { //模板方法 public final void templateMethod(){ method1(); method2();//勾子方法 method3();//抽象方法 } private void method1(){ System.out.println("父类实现业务逻辑"); } public void method2(){ System.out.println("父类默认实现,子类可覆盖"); } protected abstract void method3();//子类负责实现业务逻辑 }
父类中有三个方法,分别是method1(),method2()和method3()。
method1()是私有方法,有且只能由父类实现逻辑,由于方法是private的,所以只能父类调用。
method2()是所谓的勾子方法。父类提供默认实现,如果子类觉得有必要定制,则可以覆盖父类的默认实现。
method3()是子类必须实现的方法,即制定的步骤。
由此可看出,算法的流程执行顺序是由父类掌控的,子类只能配合。
public class TemplatePatternImpl extends TemplatePattern { @Override protected void method3() { System.out.println("method3()在子类TemplatePatternImpl中实现了!!"); } }这个子类只覆盖了必须覆盖的方法
TemplatePattern t1 = new TemplatePatternImpl(); t1.templateMethod();输出
父类实现业务逻辑 父类默认实现,子类可覆盖 method3()在子类TemplatePatternImpl中实现了!!
public List<User> query() { List<User> userList = new ArrayList<User>(); String sql = "select * from User"; Connection con = null; PreparedStatement pst = null; ResultSet rs = null; try { con = HsqldbUtil.getConnection(); pst = con.prepareStatement(sql); rs = pst.executeQuery(); User user = null; while (rs.next()) { user = new User(); user.setId(rs.getInt("id")); user.setUserName(rs.getString("user_name")); user.setBirth(rs.getDate("birth")); user.setCreateDate(rs.getDate("create_date")); userList.add(user); } } catch (SQLException e) { e.printStackTrace(); }finally{ if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } try { pst.close(); } catch (SQLException e) { e.printStackTrace(); } try { if(!con.isClosed()){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } catch (SQLException e) { e.printStackTrace(); } } return userList; }在面向对象编程的年代里,这样的代码简直不能上人容忍。试想,上面我们只是做了一张表的查询,如果我们要做第2张表,第3张表呢,又是一堆重复的代码:
1、获取connection
2、获取statement
3、获取resultset
4、遍历resultset并封装成集合
5、依次关闭connection,statement,resultset,而且还要考虑各种异常
6、.....
这时候,使用模板模式的时机到了!!!
通过观察我们发现上面步骤中大多数都是重复的,可复用的,只有在遍历ResultSet并封装成集合的这一步骤是可定制的,因为每张表都映射不同的java bean。这部分代码是没有办法复用的,只能定制。那就让我们用一个抽象的父类把它们封装一下吧:
public abstract class JdbcTemplate { //template method public final Object execute(String sql) throws SQLException{ Connection con = HsqldbUtil.getConnection(); Statement stmt = null; try { stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); Object result = doInStatement(rs);//abstract method return result; } catch (SQLException ex) { ex.printStackTrace(); throw ex; } finally { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } try { if(!con.isClosed()){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } catch (SQLException e) { e.printStackTrace(); } } } //implements in subclass protected abstract Object doInStatement(ResultSet rs); }在上面这个抽象类中,封装了SUN JDBC API的主要流程,而遍历ResultSet这一步骤则放到抽象方法doInStatement()中,由子类负责实现。
好,我们来定义一个子类,并继承上面的父类:
public class JdbcTemplateUserImpl extends JdbcTemplate { @Override protected Object doInStatement(ResultSet rs) { List<User> userList = new ArrayList<User>(); try { User user = null; while (rs.next()) { user = new User(); user.setId(rs.getInt("id")); user.setUserName(rs.getString("user_name")); user.setBirth(rs.getDate("birth")); user.setCreateDate(rs.getDate("create_date")); userList.add(user); } return userList; } catch (SQLException e) { e.printStackTrace(); return null; } } }
试想,如果我每次用jdbcTemplate时,都要继承一下上面的父类,是不是有些不方面呢?
那就让我们甩掉abstract这顶帽子吧,这时,就该callback(回调)上场了
所谓回调,就是方法参数中传递一个接口,父类在调用此方法时,必须调用方法中传递的接口的实现类。
那我们就来把上面的代码改造一下,改用回调实现吧:
首先,我们来定义一个回调接口:
public interface StatementCallback { Object doInStatement(Statement stmt) throws SQLException; }这时候,我们就要方法的签名改一下了:
private final Object execute(StatementCallback action) throws SQLException
Object result = action.doInStatement(stmt);
public Object query(StatementCallback stmt) throws SQLException{ return execute(stmt); }
我们来写一个测试类Test.java测试一下吧:
这时候,访问有两种方式,一种是内部类的方式,一种是匿名方式。
//内部类方式 public Object query(final String sql) throws SQLException { class QueryStatementCallback implements StatementCallback { public Object doInStatement(Statement stmt) throws SQLException { ResultSet rs = stmt.executeQuery(sql); List<User> userList = new ArrayList<User>(); User user = null; while (rs.next()) { user = new User(); user.setId(rs.getInt("id")); user.setUserName(rs.getString("user_name")); user.setBirth(rs.getDate("birth")); user.setCreateDate(rs.getDate("create_date")); userList.add(user); } return userList; } } JdbcTemplate jt = new JdbcTemplate(); return jt.query(new QueryStatementCallback()); }
为什么spring不用传统的模板方法,而加之以Callback进行配合呢?
试想,如果父类中有10个抽象方法,而继承它的所有子类则要将这10个抽象方法全部实现,子类显得非常臃肿。而有时候某个子类只需要定制父类中的某一个方法该怎么办呢?这个时候就要用到Callback回调了。
阅读全文
0 0
- Spring中模板模式和回调模式(一)
- Spring中模板模式和回调模式的讲解
- Spring中模板模式和回调模式的讲解
- Spring中模板模式和回调模式的讲解
- Spring中模板模式和回调模式的讲解
- Spring中模板模式和回调模式的讲解
- Spring中模板模式和回调模式的讲解
- Spring中模板模式和回调模式(二)
- Spring模板模式和回调接口
- 模板方法模式和回调模式
- 设计模式一模板方法模式(spring)
- 设计模式一模板方法模式(spring)
- spring中模板模式的应用
- spring 中jdbc模板模式应用
- spring中应用模板模式封装ElasticsearchTemplate
- spring-模板设计模式
- 参考Spring模板模式和回调接口的一个应用
- 模板回调模式
- react native 将android studio external libraries里的库替换成自己的编译的库
- C
- C# DataGridView显示行号的三种方法
- 递归的函数
- Java IoC模式(依赖、依赖倒置DIP、依赖注入DI、控制反转)
- Spring中模板模式和回调模式(一)
- 关于Monkey的一些测试记录
- 猴子选大王问题
- SSL/TSL握手过程详解
- 递归——实现猴子选大王的问题
- Python3防止死锁的加锁机制
- hdu 2082 2079 母函数水
- unity开发 --------- ExecuteInEditMode
- CCF CSP 201604-1 折点计数(Java-100分)