前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java设计模式之模板模式,站在巨人的肩膀上成功

java设计模式之模板模式,站在巨人的肩膀上成功

作者头像
用户4361942
发布2019-05-24 17:03:42
1.3K0
发布2019-05-24 17:03:42
举报
文章被收录于专栏:java程序员思维java程序员思维

模板模式

模板模式(Template Pattern),定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤。这种类型的设计模式属于行为型模式。

模板模式解决的问题

一些方法通用,却在每一个子类都重新写了这一方法,带来大量重复的代码的问题。相同的部分父类给出统一的模板,不同的部分,子类进行重写。

命令模式模式角色

AbstractTemplate(抽象类):在抽象类中定义了一系列基本操作,这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。

ConcreteTemplate(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。

模板抽象类方法类型

抽象方法:在抽象类声明、由其具体子类实现。

具体方法:在抽象类中声明并实现,在具体子类中可以继承或重写。

钩子方法:在抽象类中声明并实现(可以是空的实现),子类视情况进行重写覆盖,一般是逻辑判断方法。

模板方法:定义统一模板算法的方法,提供实现方法,子类一般不需要重写。

模板模式和策略模式的区别

模板模式定义了一个统一的算法,子类可以对算法的某一些步骤,进行覆盖重写,可以提高代码的复用率。同过继承的方式实现,依赖比较强,不够灵活。策略模式每个子类都是一种实现,可以完全不相同,即便算法之间存在共性,也需要在每个子类重新实现,通过聚合的方式实现,可以动态的改变算法,比较灵活。

代码实现

代码语言:javascript
复制
/**
 * 抽象模板
 */
public abstract class Game {
 /**
 * 具体方法
 */
 public void initialize(){
 System.out.println("game initialize .........");
 }
 /**
 * 抽象方法
 */
 abstract void startPlay();
 abstract void endPlay();
 /**
 * 钩子方法
 * @return 是否需要结束
 */
 boolean isNeedEnd(){
 return false;
 }
 /**
 * 模板方法
 * final修饰 不允许子类修改
 * 每一个游戏先初始化、开始游戏 是否需要结束游戏 根据钩子进行判断
 */
 public final void play(){
 //初始化游戏
 initialize();
 //开始游戏
 startPlay();
 if(isNeedEnd()){
 //结束游戏
 endPlay();
 }
 }
}
代码语言:javascript
复制
/**
 * 具体模板
 * 足球游戏
 */
public class Football extends Game{
 @Override
 void endPlay() {
 System.out.println("Football Game Finished!");
 }
 @Override
 void startPlay() {
 System.out.println("Football Game Started. Enjoy the game!");
 }
 @Override
 boolean isNeedEnd() {
 return false;
 }
}
代码语言:javascript
复制
/**
 * 模板测试类
 */
public class TemplateModeTest {
 public static void main(String[] args) {
 Game game = new Basketball();
 game.play();
 game = new Football();
 game.play();
 }
}

运行结果:

JDK和框架中的模板模式

代码语言:javascript
复制
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
 Assert.notNull(action, "Callback object must not be null");
 Connection con = DataSourceUtils.getConnection(getDataSource());
 Statement stmt = null;
 try {
 Connection conToUse = con;
 if (this.nativeJdbcExtractor != null &&
 this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
 conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
 }
 stmt = conToUse.createStatement();
 applyStatementSettings(stmt);
 Statement stmtToUse = stmt;
 if (this.nativeJdbcExtractor != null) {
 stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
 }
 T result = action.doInStatement(stmtToUse);
 handleWarnings(stmt);
 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.
 JdbcUtils.closeStatement(stmt);
 stmt = null;
 DataSourceUtils.releaseConnection(con, getDataSource());
 con = null;
 throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
 }
 finally {
 JdbcUtils.closeStatement(stmt);
 DataSourceUtils.releaseConnection(con, getDataSource());
 }
}
代码语言:javascript
复制
public boolean isSkipResultsProcessing() {
 return this.skipResultsProcessing;
}

spring中的JdbcTemplate、RedisTemplate、RestTemplate都是典型的模板模式,都是继承Accessor类和实现Operations接口。

优缺点

优点:封装不变部分,扩展可变部分。 提取公共代码,便于维护。 行为由父类控制,子类实现。

缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

生活中的命令模式

PPT模板,从网上下载自己喜欢的PPT模板,在不改变大的整体框架的情况下,替换掉部分内容,比如文字内容、部分图片内容,可以很大程度提高产出率。

机器学习中的迁移学习,也是一个典型的模板模式,机器学习中提供了很多模板模型,VGG19、ResNet50、InceptionV3,如果我们自己训练这个模型需要花很长的时间,几周或者更长的时间,可以把别人训练好的模型作为模板,做一些细微的调整,去训练我们自己的样本数据,得到一个适合我们特有数据的模型,只需要训练比较短的时间,就能得到一个比较好的模型。

我的启发

模板模式就像站在巨人的肩膀上,在大方向上借鉴别人的经验,进行适当的调整,以满足我们自己定制化的需求。当我们不具备造轮子的能力的时候,合理选择适合的模板也是一种不错的选择。

设计模式系列文章历史

java设计模式之适配器模式,大丈夫能屈能伸

Head First 设计模式之命令模式,各司其职提高效率

Head First 设计模式之装饰器模式,因为参与,所以认同

Head First 设计模式之单例模式,每个人都是唯一

Head First 设计模式之观察者模式,你我都是发布者和订阅者

Head first 设计模式之策略模式,来源于生活,用之于生活

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java程序员思维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档