`
kulinglei
  • 浏览: 101807 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

模板方法和回调方法的困惑

阅读更多
我对他们的理解:
先看一个例子:

引用
jdbcTemplate.update()的源码

1. public int update(final String sql) throws DataAccessException {  
2.     Assert.notNull(sql, "SQL must not be null");  
3.     if (logger.isDebugEnabled()) {  
4.         logger.debug("Executing SQL update [" + sql + "]");  
5.     }  
6.  
7.     class UpdateStatementCallback implements StatementCallback, SqlProvider {  
8.         public Object doInStatement(Statement stmt) throws SQLException {  
9.             int rows = stmt.executeUpdate(sql);  
10.             if (logger.isDebugEnabled()) {  
11.                 logger.debug("SQL update affected " + rows + " rows");  
12.             }  
13.             return new Integer(rows);  
14.         }  
15.         public String getSql() {  
16.             return sql;  
17.         }  
18.     }  
19.     return ((Integer) <SPAN style="COLOR: #888888">execute</SPAN>(new UpdateStatementCallback())).intValue();  
20. }

1. public Object execute(StatementCallback action) throws DataAccessException {  
2.     Assert.notNull(action, "Callback object must not be null");  
3.  
4.     Connection con = DataSourceUtils.getConnection(getDataSource());  
5.     Statement stmt = null;  
6.     try {  
7.         Connection conToUse = con;  
8.         if (this.nativeJdbcExtractor != null &&  
9.                 this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {  
10.             conToUse = this.nativeJdbcExtractor.getNativeConnection(con);  
11.         }  
12.         stmt = conToUse.createStatement();  
13.         applyStatementSettings(stmt);  
14.         Statement stmtToUse = stmt;  
15.         if (this.nativeJdbcExtractor != null) {  
16.             stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);  
17.         }  
18.         Object result = <SPAN style="COLOR: #000000">action.doInStatement(stmtToUse);</SPAN>  
19.         handleWarnings(stmt.getWarnings());  
20.         return result;  
21.     }  
22.     catch (SQLException ex) {  
23.         // Release Connection early, to avoid potential connection pool deadlock  
24.         // in the case when the exception translator hasn't been initialized yet.  
25.         JdbcUtils.closeStatement(stmt);  
26.         stmt = null;  
27.         DataSourceUtils.releaseConnection(con, getDataSource());  
28.         con = null;  
29.         throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);  
30.     }  
31.     finally {  
32.         JdbcUtils.closeStatement(stmt);  
33.         DataSourceUtils.releaseConnection(con, getDataSource());  
34.     }  
35. } 


eg:A回调方法。B模板方法

怎样才能把B中的动态代码写成固定的啊?????
我们可以采用多态的方法,上面的代码就是采用多态的方法,

回调的方法是多态的(这样我们就可以写不同的代码了)


刚开时时,我认为模块和回调是为了代码的复用.我们可以把重复的代码写在模板中,把变化的写在回调方法中,
现在感觉模块和回调确实可以复用代码,但这不是他存在的主要原因。

谁能说说他主要的用途
貌似一切皆在他的名字中 模板(可以理解为相同的流程)
我们可以吧流程中不同的内容提取出来,
                       回调:貌似可以‘动态’的加入代码

希望高手来交流



分享到:
评论
6 楼 kulinglei 2009-03-26  
凤舞凰扬 写道
     模板方法时一种模式,属于静态表现对象的结构关系。其中的抽象模板方法是构成一个整体行为中的一部分,这部分的行为抽象已经确定,而只是将具体的实现延迟到子类完成。
     回调不算是模式,它更多地是处理对象间的相互调用关系。回调一般是行为已经确定,而不确定调用者时常用。回调也就是把具体的行为传递给调用者。因为模板和回调都是将实际的对象调用关系延迟,所以会让人有一种错觉。其实很多时候,回调是用在事件处理、消息通知等,比如我们都知道的钩子程序。从这个角度说,回调是与观察器模式相似的,或者应该说回调是观察器模式的主要构成。
      在spring 的jdbctempate中确实用了回调,但是,它其实是一种变异的模板方法模式,只是因为用了无名内部类,所以让人忽略了对于callback中模板方法的实现而已。而所谓的回调其实只是通过一个统一的方法将模板实现类注入而已,将callback中模板方法所在的整体行为从callback中抽取到独立的template中了。
      不知道是否说得够清楚了,不过spring这个设计是一个蛮经典的设计。唯一的缺点就是随着方法调用的增多会导致JVM的OldGen中,匿名class对象会增多,每次full GC都会导致class unloading的情况。

unsid 写道
实现功能差不多,回调简洁一些,因为模板方法要为每个类型生成一个最终实现类,回调类可以用无名内隐类来代替.另外使用回调的话可以放心地把主类声明为final而避免因子类复写了不该复写的方法而导致的错误.用回调还是模版方法,我觉得看情况吧,如果动态的方法中要用到好多类的变量,那么回调函数要有一个很长的参数表,非常不好理解,如果回调函数要实现多于一个的方法,那么无法用内隐类,也没有简洁性了,总之在设计过程中,能不用继承就不用.


你们两个是正确的。
5 楼 kulinglei 2009-03-26  
凤舞凰扬 写道
     模板方法时一种模式,属于静态表现对象的结构关系。其中的抽象模板方法是构成一个整体行为中的一部分,这部分的行为抽象已经确定,而只是将具体的实现延迟到子类完成。
     回调不算是模式,它更多地是处理对象间的相互调用关系。回调一般是行为已经确定,而不确定调用者时常用。回调也就是把具体的行为传递给调用者。因为模板和回调都是将实际的对象调用关系延迟,所以会让人有一种错觉。其实很多时候,回调是用在事件处理、消息通知等,比如我们都知道的钩子程序。从这个角度说,回调是与观察器模式相似的,或者应该说回调是观察器模式的主要构成。
      在spring 的jdbctempate中确实用了回调,但是,它其实是一种变异的模板方法模式,只是因为用了无名内部类,所以让人忽略了对于callback中模板方法的实现而已。而所谓的回调其实只是通过一个统一的方法将模板实现类注入而已,将callback中模板方法所在的整体行为从callback中抽取到独立的template中了。
      不知道是否说得够清楚了,不过spring这个设计是一个蛮经典的设计。唯一的缺点就是随着方法调用的增多会导致JVM的OldGen中,匿名class对象会增多,每次full GC都会导致class unloading的情况。

感觉你说的和我理解的相差好大,我在好好看看,设计模式
4 楼 凤舞凰扬 2009-03-26  
     模板方法时一种模式,属于静态表现对象的结构关系。其中的抽象模板方法是构成一个整体行为中的一部分,这部分的行为抽象已经确定,而只是将具体的实现延迟到子类完成。
     回调不算是模式,它更多地是处理对象间的相互调用关系。回调一般是行为已经确定,而不确定调用者时常用。回调也就是把具体的行为传递给调用者。因为模板和回调都是将实际的对象调用关系延迟,所以会让人有一种错觉。其实很多时候,回调是用在事件处理、消息通知等,比如我们都知道的钩子程序。从这个角度说,回调是与观察器模式相似的,或者应该说回调是观察器模式的主要构成。
      在spring 的jdbctempate中确实用了回调,但是,它其实是一种变异的模板方法模式,只是因为用了无名内部类,所以让人忽略了对于callback中模板方法的实现而已。而所谓的回调其实只是通过一个统一的方法将模板实现类注入而已,将callback中模板方法所在的整体行为从callback中抽取到独立的template中了。
      不知道是否说得够清楚了,不过spring这个设计是一个蛮经典的设计。唯一的缺点就是随着方法调用的增多会导致JVM的OldGen中,匿名class对象会增多,每次full GC都会导致class unloading的情况。
3 楼 kulinglei 2009-03-25  
unsid 写道
另外,区别是回调还是模板方法,还有一个很重要的依据,你所变化的类是不是具有"一次性特征",思考一下comparable接口,为什么不设计在list之上?因为list里的元素排序方式单一性一次性,比如这次按价格排序只代表这次,下次按出厂日期排序.而你的例子里,适合用模板方法,因为你的实现类相对稳定,总共不会有太多种类的操作.其实回调就是"访问者"模式最简单的实现.

不明白,模板和回调是一起使用的吧???

我在模板方法中去回调。

你说的貌似他们是分开的,可以单独存在,
2 楼 unsid 2009-03-25  
另外,区别是回调还是模板方法,还有一个很重要的依据,你所变化的类是不是具有"一次性特征",思考一下comparable接口,为什么不设计在list之上?因为list里的元素排序方式单一性一次性,比如这次按价格排序只代表这次,下次按出厂日期排序.而你的例子里,适合用模板方法,因为你的实现类相对稳定,总共不会有太多种类的操作.其实回调就是"访问者"模式最简单的实现.
1 楼 unsid 2009-03-25  
实现功能差不多,回调简洁一些,因为模板方法要为每个类型生成一个最终实现类,回调类可以用无名内隐类来代替.另外使用回调的话可以放心地把主类声明为final而避免因子类复写了不该复写的方法而导致的错误.用回调还是模版方法,我觉得看情况吧,如果动态的方法中要用到好多类的变量,那么回调函数要有一个很长的参数表,非常不好理解,如果回调函数要实现多于一个的方法,那么无法用内隐类,也没有简洁性了,总之在设计过程中,能不用继承就不用.

相关推荐

    信用卡付款网页模板

    1. **用户体验**:模板应具有直观的布局,清晰的指示,以及易于理解的步骤,以减少用户的困惑和操作难度。页面应该简洁明了,避免过多的广告或无关信息干扰。 2. **安全性**:考虑到涉及敏感的财务信息,模板必须...

    悟透JavaScript

    原型链则解释了JavaScript如何实现对象的继承,通过__proto__属性或Object.create()方法,一个对象可以继承另一个对象的属性和方法。作用域和作用域链决定了变量的可见性和生命周期,而this的指向在函数调用方式不同...

    Javascript忍者的秘密

    通过原型链,我们可以访问和继承对象的属性和方法。 其次,闭包是JavaScript中的另一个重要概念。闭包允许函数访问并操作外部作用域的变量,即使在其定义的作用域之外。这种特性使得闭包在创建私有变量、模块化代码...

    JavaScript 权威指南(第五版)

    5. **异步编程**:JavaScript是单线程执行的,但通过事件循环和回调函数、Promise、async/await等方式,可以实现非阻塞的异步处理,这在处理网络请求、定时任务等场景中尤其重要。 6. **数组与集合**:JavaScript...

    一个界面显示“等待”处理的共有类

    3. **异步编程**:在Java或Android等平台中,可以使用异步任务、回调函数、Future、Promise、RxJava等技术实现后台任务和UI更新的解耦,确保用户界面的流畅性。 4. **线程同步**:在某些情况下,可能需要控制线程间...

    我最近在重新学 JavaScript, 巩固一下细节, 也写一个“WTF JavaScript极简入门”,供新人学习.zip

    5. **异步编程**:JavaScript是单线程的,但通过事件循环和回调函数、Promise、async/await实现了异步处理,避免了阻塞主线程。 6. **闭包**:闭包是JavaScript中的一个重要特性,它允许内部函数访问并操作外部函数...

    YouDon'tKnowJS中文版

    通过原型链,对象可以继承其他对象的属性和方法。书中详细解释了如何使用原型进行对象扩展和继承。 3. **类型与类型转换**:JavaScript是一种动态类型语言,书中深入讨论了基本类型(如字符串、数字、布尔值)和...

    Spring.3.x企业应用开发实战(完整版).part2

    8.3.1 使用模板和回调机制 8.3.2 Spring为不同持久化技术所提供的模板类 8.4 数据源 8.4.1 配置一个数据源 8.4.2 获取JNDI数据源 8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础...

    Spring3.x企业应用开发实战(完整版) part1

    8.3.1 使用模板和回调机制 8.3.2 Spring为不同持久化技术所提供的模板类 8.4 数据源 8.4.1 配置一个数据源 8.4.2 获取JNDI数据源 8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础...

    初学者文件,最终项目和常见问题解答为我的完整JavaScript课程.zip

    6. **异步编程**:包括回调函数、Promise和async/await,这些都是处理非同步任务,如Ajax请求、定时器等的方式。 7. **ES6及后续版本的新特性**:例如箭头函数、模板字符串、解构赋值、类和模块等,这些都是现代...

    JavaScript 语言精粹

    此外,《JavaScript语言精粹》还会深入讨论作用域、变量提升、this关键字、事件处理、DOM操作以及异步编程,如回调函数、Promise和async/await。这些知识点对于前端开发人员来说至关重要,因为它们直接影响到网页的...

    js 省市县三级联动,特别好用

    6. **异步处理**:如果数据是从服务器动态获取的,可能需要使用Ajax(如`fetch`或`XMLHttpRequest`)来请求数据,然后在回调函数中更新下拉框。 7. **初始加载**:页面加载时,需要根据默认的省份数据填充城市...

    effective c++.pdf

    8. **了解运算符重载的陷阱**:运算符重载可以增加代码的表达性,但不当使用可能导致困惑和错误。遵循运算符的自然语义,并注意潜在的副作用。 9. **善用成员函数指针**:成员函数指针可以用于回调或策略模式,但其...

    js代码-给余晖的代码,笨死,文档都不看

    4. 异步编程:JavaScript中的回调函数、Promise和async/await是处理异步操作的关键。了解这些机制可以帮助避免回调地狱,使代码更易于理解和调试。 5. DOM操作:在前端开发中,与DOM交互是常见的任务,掌握`...

    无用统计

    接下来,我们可以聊聊JavaScript的异步编程,如回调函数、Promise和async/await。这些机制解决了JavaScript的单线程执行模型下的阻塞问题,使得开发者可以编写非阻塞的代码,提高程序的执行效率。 此外,JavaScript...

    advanced-topics

    原型链允许对象间共享属性和方法,使得代码复用和组织更加高效。理解这个机制对于编写可扩展和可维护的代码至关重要。 接着,闭包是JavaScript中的另一个重要概念。闭包是一种特殊的作用域,它可以访问其自身、函数...

    周三

    在周三的学习中,我们还可以深入探讨JavaScript的异步编程,包括回调函数、Promise、async/await等概念。异步编程是处理I/O密集型任务和网络请求的关键,避免了程序因等待响应而阻塞。另外,JavaScript的模块系统,...

    Javascript-Crash-Course

    异步编程是JavaScript的一大特色,主要体现在回调函数、Promise和async/await。理解如何处理非阻塞代码对于编写高性能的Web应用至关重要。 最后,课程可能还会涉及JavaScript的现代特性,如ES6+的新语法(例如let和...

    网络日志:记录我个人的前端问题,以及解决方案,留待以后自己查看

    3. **异步编程**:JavaScript的异步编程是学习难点,包括回调函数、Promise、async/await等。作者可能记录了如何避免回调地狱,如何优雅地处理异步任务,以及在实际项目中的应用案例。 4. **面向对象编程**:理解类...

    JSJargon-crx插件

    它代表了一个可能尚未完成的异步操作的结果,提供了一种处理回调地狱的方法,使得异步代码更易于理解和管理。 2. **ES6/ES2015+**:这是JavaScript的版本代号,表示自2015年开始引入的一系列新特性和语法改进,如...

Global site tag (gtag.js) - Google Analytics