博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模板方法模式(Template Method)
阅读量:6849 次
发布时间:2019-06-26

本文共 5095 字,大约阅读时间需要 16 分钟。

模板方法模式:定义一个算法骨架,并将其中一部分具体实现延迟到子类。他使得子类可以不必改变一个算法结构即可重定义该算法的某些特定步骤。

模板方法可以聚集方法实现里的公共部分,而把变化的部分延迟到了子类

package templatemethod;public abstract class Salary {    /** 算法骨架 */    public float realIncome(float salary) {     System.out.println("公共部分");        return salary - tax(salary) - ensurance(salary);    }        /** 延迟到子类的具体实现    * 实际上这两个抽象方法就是工厂方法(Factory Method)    * GoF的设计模式里也提到了,模板方法实际上也依赖于工厂方法来实现 */    protected abstract float tax(float salary);    protected abstract float ensurance(float salary);}package templatemethod;public class BeijingSalary extends Salary {    @Override    protected float tax(float salary) {        return (float) (salary * 0.03);    }    @Override    protected float ensurance(float salary) {        return (float) (salary * 0.2);    }    }package templatemethod;public class ShanghaiSalary extends Salary {    @Override    protected float tax(float salary) {        return (float) (salary * 0.032);    }    @Override    protected float ensurance(float salary) {        return (float) (salary * 0.22);    }}package templatemethod;public class Test {    public static void main(String[] args) {        Salary bjSalary = new BeijingSalary();        Salary shSalary = new ShanghaiSalary();        float salary = 11000;        System.out.println("Beijing real income of " + salary + " is " + bjSalary.realIncome(salary));        System.out.println("Shanghai real income of " + salary + " is " + shSalary.realIncome(salary));    }}

 

程序输出:

公共部分

Beijing real income of 11000.0 is 8470.0

公共部分

Shanghai real income of 11000.0 is 8228.0

 

Spring中也有许多Template的实现,下面对于JDBCTemplate为例做个简单介绍

JDBCTemplate一般的execute()方法实现逻辑是穿如一个SQL参数和一个Callback调用类,这个Callback调用就是模板方法的实现类

如下

@Override    public 
T execute(String sql, PreparedStatementCallback
action) throws DataAccessException { return execute(new SimplePreparedStatementCreator(sql), action); }@Override public
T execute(PreparedStatementCreator psc, PreparedStatementCallback
action) throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); if (logger.isDebugEnabled()) { String sql = getSql(psc); logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : "")); } Connection con = DataSourceUtils.getConnection(getDataSource()); PreparedStatement ps = null; try { Connection conToUse = con; if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } ps = psc.createPreparedStatement(conToUse); applyStatementSettings(ps); PreparedStatement psToUse = ps; if (this.nativeJdbcExtractor != null) { psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps); } T result = action.doInPreparedStatement(psToUse); handleWarnings(ps); return result; } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } String sql = getSql(psc); psc = null; JdbcUtils.closeStatement(ps); ps = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex); } finally { if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } JdbcUtils.closeStatement(ps); DataSourceUtils.releaseConnection(con, getDataSource()); } }

 

 

而如果我们没有传入Callback类,则使用其定义的内部类替代,如下

public void execute(final String sql) throws DataAccessException {        if (logger.isDebugEnabled()) {            logger.debug("Executing SQL statement [" + sql + "]");        }        class ExecuteStatementCallback implements StatementCallback, SqlProvider {            @Override            public Object doInStatement(Statement stmt) throws SQLException {                stmt.execute(sql);                return null;            }            @Override            public String getSql() {                return sql;            }        }        execute(new ExecuteStatementCallback());    }

 

 

对于JDBCTemplate来说,它的公共部分就是获取数据库连接,获取Statement,以及他们的关闭,还有SQLException的处理,所以在JDBCTemplate的使用中我们无需再编写这些冗长的连接及关闭还有异常代码.

而Spring的模板方法实现并不依赖于继承,而是使用了接口和类的传入,这样的好处是更灵活,不是继承的话,我们不需要去实现一些我们认为不需要的抽象方法,仅需根据自己的需要调用模板方法并传入参数即可.

另外值得一提的就是Spring的持久层异常处理机制,它将表意不明的SQLException转化成了各种粒度更细的非检查性Exception,好处就是我们不需要显示的去try catch,而且在出现异常后可以更明了的知道异常的信息.

转载地址:http://leeul.baihongyu.com/

你可能感兴趣的文章
关于Java的权限修饰符(public,private,protected,默认friendly)
查看>>
hdu 5396 Expression(区间dp)
查看>>
Oracle创建表空间、创建用户以及授权、查看权限
查看>>
Gatling新一代压力测试工具,新一代服务器性能测试工具Gatling
查看>>
深入理解红黑树
查看>>
linux内核学习-建议路线
查看>>
华为上机:对数计数器
查看>>
Spring中的Autowired注解和Resource注解的区别
查看>>
电脑待机、休眠、睡眠的区别
查看>>
滚动条
查看>>
Xamarin XAML语言教程控件模板的模板绑定
查看>>
上传通用化 VHD 并使用它在 Azure 中创建新 VM
查看>>
SSM Spring +SpringMVC+Mybatis 整合配置 及pom.xml
查看>>
php 字符串处理
查看>>
修改apache配置文件去除thinkphp url中的index.php(转)
查看>>
春困的经方
查看>>
asccii 表
查看>>
PHP5学习笔记-变量
查看>>
Jquery隔行变色(原创)
查看>>
(2)入门指南——(7)添加jquery代码(Adding our jQuery code)
查看>>