目录

1、模板方法设计模式

2、继承实现方案

3、依赖实现方案

3.1 spring-jdbc 中的 JdbcTemplate

3.2  阿里分布式事务框架Seata中的ExecuteTemplate


1、模板方法设计模式

模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
该模式的主要优点如下。

  1. 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
  2. 它在父类中提取了公共的部分代码,便于代码复用。
  3. 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

2、继承实现方案

模板方法模式需要注意抽象类与具体子类之间的协作。它用到了虚函数的多态性技术以及“不用调用我,让我来调用你”的反向控制技术。现在来介绍它们的基本结构。

模板方法模式包含以下主要角色。

1)抽象类/抽象模板(Abstract Class)

抽象模板类,负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。

① 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
② 基本方法:是整个算法中的一个步骤,包含以下几种类型。

  • 抽象方法:在抽象类中声明,由具体子类实现。
  • 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
  • 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。

2)具体子类/具体实现(Concrete Class)

具体实现类,实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。

模板方法模式的结构图如图 1 所示。

JDK中的InputStream是采用的继承实现方案的模板方法设计模式,代码如下:

//这是一个模板方法
public int read(byte b[], int off, int len) throws IOException {if (b == null) {throw new NullPointerException();} else if (off < 0 || len < 0 || len > b.length - off) {throw new IndexOutOfBoundsException();} else if (len == 0) {return 0;}int c = read();if (c == -1) {return -1;}b[off] = (byte)c;int i = 1;try {for (; i < len ; i++) {c = read();//read()是一个抽象方法,由各子类进行实现if (c == -1) {break;}b[off + i] = (byte)c;}} catch (IOException ee) {}return i;}

3、依赖实现方案

3.1 spring-jdbc 中的 JdbcTemplate

模板类一个具体的类,将个性化的实现作为方法的参数,这样就避免类之间的继承关系,通过依赖关系实现了模板方法设计模式,这里给一个spring-jdbc中的示例,JdbcTemplate中的代码片段,如下:

 //这是一个模板方法@Override@Nullablepublic <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
// PreparedStatementCallback是一个回调函数,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(obtainDataSource());PreparedStatement ps = null;try {ps = psc.createPreparedStatement(con);applyStatementSettings(ps);T result = action.doInPreparedStatement(ps);//T result = action.doInPreparedStatement(ps);这个操作可以个性化实现,由// 会传入的参数action来决定真正的实现业务逻辑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 translateException("PreparedStatementCallback", sql, ex);}finally {if (psc instanceof ParameterDisposer) {((ParameterDisposer) psc).cleanupParameters();}JdbcUtils.closeStatement(ps);DataSourceUtils.releaseConnection(con, getDataSource());}}

3.2  阿里分布式事务框架Seata中的ExecuteTemplate

 //模板方法
/*** Execute t.** @param <T>               the type parameter* @param <S>               the type parameter* @param sqlRecognizer     the sql recognizer* @param statementProxy    the statement proxy* @param statementCallback the statement callback* @param args              the args* @return the t* @throws SQLException the sql exception*/public static <T, S extends Statement> T execute(List<SQLRecognizer> sqlRecognizers,StatementProxy<S> statementProxy,StatementCallback<T, S> statementCallback,Object... args) throws SQLException {if (!RootContext.inGlobalTransaction() && !RootContext.requireGlobalLock()) {// Just work as original statement// statementCallback是个性化实现return statementCallback.execute(statementProxy.getTargetStatement(), args);}if (sqlRecognizers == null) {sqlRecognizers = SQLVisitorFactory.get(statementProxy.getTargetSQL(),statementProxy.getConnectionProxy().getDbType());}Executor<T> executor;if (CollectionUtils.isEmpty(sqlRecognizers)) {executor = new PlainExecutor<>(statementProxy, statementCallback);} else {if (sqlRecognizers.size() == 1) {SQLRecognizer sqlRecognizer = sqlRecognizers.get(0);switch (sqlRecognizer.getSQLType()) {case INSERT:executor = new InsertExecutor<>(statementProxy, statementCallback, sqlRecognizer);break;case UPDATE:executor = new UpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);break;case DELETE:executor = new DeleteExecutor<>(statementProxy, statementCallback, sqlRecognizer);break;case SELECT_FOR_UPDATE:executor = new SelectForUpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);break;default:executor = new PlainExecutor<>(statementProxy, statementCallback);break;}} else {executor = new MultiExecutor<>(statementProxy, statementCallback, sqlRecognizers);}}T rs;try {rs = executor.execute(args);} catch (Throwable ex) {if (!(ex instanceof SQLException)) {// Turn other exception into SQLExceptionex = new SQLException(ex);}throw (SQLException) ex;}return rs;}
}

模板方法设计模式两种实现方案相关推荐

  1. android 热更新 方案,热更新-热更新app开发的两种系统方案!

    针对app开发工作人员来讲,除开要会编码,热更新也是一定要学好和把握的方法,从技术性视角而言,热更新对Android和iOS各自有不一样的系统软件方案,为了更好地让大伙儿掌握这二种系统方案的差别,今日 ...

  2. 处理接口幂等性的两种常见方案

    在上周发布的 TienChin 项目视频中,我和大家一共梳理了六种幂等性解决方案,接口幂等性处理算是一个非常常见的需求了,我们在很多项目中其实都会遇到.今天我们来看看两种比较简单的实现思路. 1. 接 ...

  3. 两种复试方案!这所大学发布考研复试相关通知!

    前段时间,小编推送过一些文章,描述了部分大学可能采用网络复试的问题: 真的要[网络复试]?三所211大学发通知! 但是后来,由于疫情发展变化较快,也不清楚到底用什么复试方式,因此这些消息也没有后续了. ...

  4. Apache之——多虚拟主机多站点配置的两种实现方案

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/48213523 Apache中配置多主机多站点,可以通过两种方式实现: 将同一个域名 ...

  5. (三)Redis两种持久化方案

    Redis的持久化策略:2种 RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘.RDB是Redis默认采用的持久化方 ...

  6. EHIGH恒高:大话UWB技术之TDOA与TOF两种技术方案对比

    超宽带(UWB技术)是一种基于IEEE802.15.4a和802.15.4z标准的无线电技术,它能够非常准确地测量无线电信号的飞行时间,从而实现厘米精度的距离/位置测量.不同于蓝牙.WiFi等其他定位 ...

  7. iphoneX 前端两种适配方案

    方案一: 为适应于iphoneX的齐刘海,ios11的WebView Viewport对于顶部做了调整. iphoneX Viewport 手机浏览器是把页面放在一个虚拟的"窗口" ...

  8. 日均数据量千万级,MySQL、TiDB 两种存储方案的落地对比

    盖娅广告匹配系统(GaeaAD)用于支撑盖娅互娱全平台实时广告投放系统,需要将广告数据和游戏 SDK 上报的信息进行近实时匹配,本质上来说需要实时的根据各个渠道的广告投放与相应渠道带来的游戏玩家数据进 ...

  9. PHP+MySQL 无限级分类的两种实现方案

    方案一: 表结构: id int primary key auto_increment; name varchar(40); pid int default 0; #父类id,默认值为0 顶级分类的 ...

最新文章

  1. Swift 字面量表达
  2. error: Your local changes to the following files would be overwritten by merge
  3. ios自定义日期、时间、城市选择器
  4. 2021-06-05
  5. 28、OSPF配置实验之负载均衡
  6. Python基础——PyCharm版本——第四章、基础语法-分支语句(条件判断if语句)
  7. Redis之数据结构底层实现
  8. 图片图层隐写_【软件】imageIN · 图影-隐藏文件到图片,简单轻快的图片隐写工具...
  9. 4. Spring 如何通过 XML 文件配置Bean,以及如何获取Bean
  10. 各种搜索算法比较--2015年7月26日16:42:45V1.0版
  11. spring基础——<bean>scope属性
  12. vue day8 table page
  13. linux两台电脑直连传数据,两台MAC电脑通过局域网快速传输文件
  14. yafu 下载_YAFUD
  15. Java调用Gdal写Esri ShapeFile文件工具类
  16. gerrit常见问题及解决方法
  17. 英伟达最新驱动打开3d vision功能
  18. 【C++小游戏】推箱子代码+详解
  19. ISCC 2022 wp
  20. 切换WiFi并配置静态或动态IP

热门文章

  1. 第六章 第一节 文本控件
  2. MATLAB实现在不同Es/N0情况下,QPSK、16QAM、64QAM误码率结果仿真图(包含软硬判决)
  3. 什么是ISTQB认证
  4. DigiCert和GlobalSign单域名OV SSL证书对比评测
  5. 工具篇——MoneyFormatUtil(用于将人民币小写金额转换成大写金额)
  6. 简单通用QQ/微信跳转浏览器打开代码
  7. 两年,从纯小白到腾讯阿里,应届非计算机毕业生的2014互联网求职之路(转)...
  8. JdbcTemplate的增删改查用法
  9. 什么是计算机网络的组成和功能是什么,计算机网络的组成要素及功能是什么
  10. 特征根是复数的二阶微分方程