码迷,mamicode.com
首页 > 其他好文 > 详细

模板方法与回调函数

时间:2014-08-05 18:53:03      阅读:330      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   java   使用   os   io   

     还记得在刚开始学习JDBC时,每一次SQL执行都要经历从连接的获取、执行SQL、获取结果等,这些是一个流程性的动作。在大二时,刚刚学会没多久后,当时我正在学习JSP、Servlet(我的Java是自学的),有一个高中的同学让我帮她做课程设计。现在还依旧记得,那是一个校园一卡通项目,功能很少,整个课程设计涉及到了10多个SQL语句。

    我当时写代码时,把所有的SQL语句都写在了一个Java文件中。每一个SQL语句的执行都要经历:

// 获取连接

Connection conn=getConnection();// 自定义的

// 获取语句

PreparedStatement psmt=conn.prepareStatement(sql);

// 设置参数

// ....

// SQL 执行

 psmt.executeUpdate或者psmt.executeQuery

// 获取结果

// 从ResultSet中取数

// 关闭连接

 close()

 

 当代码写了400多行时,我就感觉到这样写太麻烦了,有没有一个模板来处理这个过程呀,这样写下去太麻烦了,这是我当时的真实想法。

    我就在想能不能把这个烦人的过程放到一个模板里呢?不同的地方只有SQL执行和结果是如何处理,前面的过程都是一样的。那么我把SQL执行与结果处理拿出来,整个过程的其他部分不变,应该是可以的吧。可以使用抽象类来完成这个功能。

当时想到的是:

bubuko.com,布布扣
public abstract class JDBCTemplate {

   private String url;

   private String driver;

   private String user;

   private String password;

   protected Connection conn;

  

   public JDBCTemplate(){

     

   }

  

   public JDBCTemplate(String driver, String url, String user, String password){

      this.driver=driver;

      this.url=url;

      this.user=user;

      this.password=password;

   }

//// getter, setter就不粘出来了。

 

public Connection getConnection(){

      try {

         Class.forName(driver);

         conn=DriverManager.getConnection(url, user, password);

      } catch (Exception e) {

        e.printStackTrace();

      }

      return conn;

    }

   

    public void close(PreparedStatement statement) throws Exception{

        if (statement!=null){

            statement.close();

        }

        if(conn!=null){

            conn.close();

        }

    }

 

protected final Object template(String sql, Object[] params){

conn=getConnection();

PreparedStatement psmt=null;

        try{

            psmt=conn.prepareStatement(sql);

            for (int i=0; i<params.length; i++){

                psmt.setObject(i+1, params[i]);

            }

return executeAndGetResult(psmt);

        }catch (Exception e){

            e.printStackTrace();

            return e;

        }

        finally {

            try{

            close(psmt);

            }catch (Exception e){

                e.printStackTrace();

            }

        }}

 

public abstract Object executeAndGetResult(PreparedStatement psmt);

}
View Code

 

这样一来,executeAndGetRresult就由子类来完成,并且也不用再写那些烦人的过程了。当时的我,并不知道,这样写其实就是应用了模板方法模式。 

 

=============================================================

 

再后来,在学习AJax时,通过网上知道一种函数:callback,回调函数,也成为钩子函数。当时对此并不了解,上网查询学习,多多少少对回调函数有种模糊的概念。当时我想到了我之前写的那个JDBCTemplate,能否使用Callback来调整代码呢?

 

于是我改造了代码:

bubuko.com,布布扣
// 添加了一个回调接口

public interface ResultSetHandler {

   public Object handle(PreparedStatement statement);

}

 

//对模板方法接口做如下调整:

protected final Object template(String sql, Object[] params, ResultSetHandler handler){

        Connection conn=getConnection();

        PreparedStatement psmt=null;

        try{

            psmt=conn.prepareStatement(sql);

            for (int i=0; i<params.length; i++){

                psmt.setObject(i+1, params[i]);

            }

            return handler.handle(psmt);

        }catch (Exception e){

            e.printStackTrace();

            return e;

        }

        finally {

            try{

            close(psmt);

            }catch (Exception e){

                e.printStackTrace();

            }

        }

    }

 
View Code

也就是说,整个调整只换了template方法中的一句:由executeAndGetResult(psmt)调整为handler.handle(psmt); 

并把tempalte的abstract去掉了。调整后,感觉这种方式比第一种更好,只是当时的我依旧不知道什么是模板方法模式。我只知道,这样写挺好的,感觉心里很爽。于是我把这个类一直保留着,尽管后来没有使用它。

 

    后来在学习设计模式的模板方法模式时,我终于知道,原来我就用过模板方法模式,只是我不知道而已。

 

=================================================================

在GOF设计模式中是这么描述设计模式的:

    模板方法定义了一个算法步骤,并允许子类为一个或者多个步骤提供实现。

 bubuko.com,布布扣

 

 

模板方法模式的类图如下:

 bubuko.com,布布扣

 

上面的类图中,primitiveOperation1、 primitiveOperation2是抽象方法,就是整个算法中的不确定部分。他们要在模板方法中使用。我第一次写的那个JDBCTemplate中的executeAndGetResult就是这样的。

 

模板方法模式体系了对抽象编程的设计原则。

 

 

使用模板方法模式的实现中,主要是通过继承的方式,让父类在运行期间可以调用子类的方法。在Java开发中,在模板方法与回调函数结合使用时,就不需要通过继承来完成变化部分的代码了,通过Java的匿名内部类,同样可以完成上面的上述功能。

例如我的JDBCTemplate的第二版中使用了接口的方式。

接下来,我在JDBCTemplate内部添加一个方法:

 

bubuko.com,布布扣
public int save(String sql, Object[] params){

       return (Integer)template(sql,params, new ResultSetHandler() {

           public Object handle(PreparedStatement statement) {

               int result=0;

               try{

                   result=  statement.executeUpdate();

               }catch (Exception e){

                   e.printStackTrace();

               }

               return result;

           }

       });

    }
View Code

这是一个save数据的方法。使用过程中调用了template(String sql, Object[] params, ResultSetHandler handler);并不是使用子类来继承JDBCTemplate 

而是子啊方法调用时使用了匿名内部类。

 

这样做(使用Callback)可以说是TemplateMethod实现方式的一个变形。

 

 至于GOF设计模式书上说的那些关于模板方法模式的其他功能,一看便知,这里就不再说明了。

 

模板方法与回调函数,布布扣,bubuko.com

模板方法与回调函数

标签:style   blog   http   color   java   使用   os   io   

原文地址:http://www.cnblogs.com/f1194361820/p/3892878.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!