一、模板方法模式

在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行顺序。但是某些步骤的具体实现是未知的,或者说某些步骤的实现与具体的环境相关。

这时我们就需要定义一个模板结构,将具体内容延迟到子类去实现。

在不改变模板结构的前提下在子类中重新定义模板中的内容。

抽象类(AbstractClass): 定义抽象的原语操作(primitive operation) ,具体的子类将重定义它们以实现一个算法, 实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义
具体子类 (ConcreteClass):  实现原语操作以完成算法中与特定子类相关的步骤。

二、案例

我们举一个最简单的例子:

1. 开机--> 2.玩手机--> 3.关机

这是我们对手机的一个最基本的操作顺序,其中开机和关机是不变的,但是玩手机这个业务却是不同的,我们可能要社交,玩游戏,听音乐或者看电影。

实现 

步骤1: 创建抽象模板结构(Abstract Class):操作手机的步骤public  abstract class AbstractClass_Phone{  /模板方法,用来控制操作手机的流程 (流程是一样的-复用)/申明为final,不希望子类覆盖这个方法,防止更改流程的执行顺序 final void phonePress(){  //第一步:开机this.powerOn();//第二步:玩手机this.playPhone();//第三步:关机this.powerOff();}  定义结构里哪些方法是所有过程都是一样的可复用的,哪些是需要子类进行实现的/第一步:开机是一样的,所以直接实现void powerOn(){  System.out.println("开机");  }  /第二步:玩手机是不一样的(社交,游戏)//所以声明为抽象方法,具体由子类实现 abstract void  playPhone();/第三步:关机是一样的,所以直接实现void  powerOff(){  System.out.println("关机");  }
}
步骤2: 创建具体模板(Concrete Class),即”社交“和”游戏“的具体步骤/社交的类public class ConcreteClass_SheJiao extend  AbstractClass_Phone{@Overridepublic void  playPhone(){  System.out.println(”聊QQ,微信“);  }
}/游戏的类public class ConcreteClass_Game extend  AbstractClass_Phone{@Overridepublic void  playPhone(){  System.out.println(”打农药,吃鸡“);  }
}
步骤3: 客户端调用-玩手机public class TemplateMethod{public static void main(String[] args){/操作手机-->社交ConcreteClass_SheJiao sheJiao= new ConcreteClass_SheJiao();SheJiao.PhoneProcess();/操作手机-->游戏ConcreteClass_Game game= new ConcreteClass_Game();Game.PhoneProcess();}    
结果输出:开机聊QQ,微信关机开机打农药,吃鸡关机

三、优缺点

优点:

  • 提高代码复用性 
    将相同部分的代码放在抽象的父类中
  • 提高了拓展性 
    将不同的代码放入不同的子类中,通过对子类的扩展增加新的行为
  • 实现了反向控制 
    通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,实现了反向控制 & 符合“开闭原则”

缺点:

  • 每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,但是更加符合“单一职责原则”,使得类的内聚性得以提高。

四、应用场景

Servlet 中的模板方法模式

HttpServlet 的简要代码如下所示

public abstract class HttpServlet extends GenericServlet {protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... }protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... }protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... }protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... }protected void doDelete(HttpServletRequest req,  HttpServletResponse resp) throws ServletException, IOException { // ... }protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... }protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... }protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();if (method.equals(METHOD_GET)) {//...} else if (method.equals(METHOD_HEAD)) {//...} else if (method.equals(METHOD_POST)) {doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req,resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req,resp);} else {//...}}   // ...省略...
}

其中service()方法是一个模板方法,这个方法调用了七个do方法中的一个或几个,完成对客户端的请求

在开发javaWeb应用时,自定义的Servlet类一般都扩展 HttpServlet 类

Mybatis的BaseExecutor接口中的模板方法模式

Executor 是 Mybatis 的核心接口之一,其中定义了数据库操作的基本方法,该接口的代码如下:

public abstract class BaseExecutor implements Executor {protected Transaction transaction;protected Executor wrapper;protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;protected PerpetualCache localCache;protected PerpetualCache localOutputParameterCache;protected Configuration configuration;protected int queryStack = 0;private boolean closed;@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {queryStack++;list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);} else {list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack == 0) {for (DeferredLoad deferredLoad : deferredLoads) {deferredLoad.load();}// issue #601deferredLoads.clear();if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;}protected abstract int doUpdate(MappedStatement ms, Object parameter)throws SQLException;protected abstract List<BatchResult> doFlushStatements(boolean isRollback)throws SQLException;protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)throws SQLException;protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)throws SQLException;// 省略....
}

BaseExecutor 中主要提供了缓存管理和事务管理的基本功能,继承 BaseExecutor 的子类只需要实现四个基本方法来完成数据库的相关操作即可,这四个方法分别是:doUpdate() 方法、doQuery() 方法、doQueryCursor() 方法、doFlushStatement() 方法,其余功能都在 BaseExecutor 中实现。

【设计模式】——模板方法模式相关推荐

  1. 在一个程序设计里,不同的功能窗口有着相似的功能实现方式,可采用设计模式---模板方法模式

        前段时间学习了一些设计模式,最近在做项目的过程中恰巧用到了其中的一个--模板方法模式.这个模式在程序设计过程中可是为小编省去了不少的代码量呢.具体是怎样应用的呢?接下来小编为您分享. 前面博文 ...

  2. 『设计模式』瑞幸咖啡还是星巴克,一杯下午茶让我明白 设计模式--模板方法模式(Template Method Pattern)

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  3. 『设计模式』设计模式--模板方法模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  4. 行为型设计模式---模板方法模式

    设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...

  5. Java设计模式-模板方法模式详解

    Java设计模式-模板方法模式 文章目录 Java设计模式-模板方法模式 0.前言 1.模板方法原理 2.模板方法模式中的角色 3.模板方法模式的UML类图 4.代码实现 5.编码测试 6.模板模式中 ...

  6. Java设计模式 - 模板方法模式

    Java设计模式 - 模板方法模式 定义一个算法的骨架,并将一些步骤通过子类表达. UML图示 要点 1. 定义一个算法的骨架 - 建立一个抽象类 2. 将一些步骤通过子类表达 - 子类继承抽象类 赋 ...

  7. linkin大话设计模式--模板方法模式

    linkin大话设计模式--模板方法模式 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后申明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不 ...

  8. JAVA 设计模式 模板方法模式

    定义 模板方法模式 (Template Method) 定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成. 模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模 ...

  9. 模板设计模式_设计模式-模板方法模式

    一.模板方法模式的定义 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计 ...

  10. 大话设计模式—模板方法模式

    在模板方法模式(TemplateMethod Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计模式属于 ...

最新文章

  1. numpy归一化_使用numpy 高效实现K-Means聚类
  2. 进程隐藏与进程保护(SSDT Hook 实现)(二)
  3. 视频编码中封装格式RMVB,AVI,264
  4. java gc时会暂停运行吗,java gc 项目终止运行
  5. ros开发增加clion常用模板及初始化配置(四)
  6. oracle数据库改语句,Oracle 惯用的修改语句
  7. mob AndroidStudio 短信SDK集成
  8. Android 开发,你遇上 Emoji 头疼吗?
  9. 陈一为担任BCF理事
  10. 计算机bios设置翻译,bios设置中文翻译的操作教程
  11. centos7 oracle11gR2安装
  12. 二维离散沃尔什变换及matlab实现
  13. 正弦余弦编码器与增量编码器的区别
  14. day13课后总结App
  15. 推广那些坑,做好渠道组合拳!
  16. 阿根廷夺冠!梅西圆梦!历届世界杯还有哪些数据看点?
  17. STC51入门笔记(郭天祥C语言)---第二节:Keil 软件使用及流水灯设计
  18. 微博红包技术探究:架构、防刷、监控和资源调度
  19. 利用ArcMap将CAD数据转为shp
  20. 2021-WWW-Learning Intents behind Interactions with Knowledge Graph for Recommendation

热门文章

  1. task2-基于小鼠的基因集数据库资源
  2. HTTP error 404.3 HTTP error 502.3
  3. 2023年1月7日:fastadmin导出数据为excel格式
  4. 基于Java的学生综合素质评估系统的设计与实现
  5. 【Linux进程/线程间通信】实现荔枝派zero与电脑串口通信
  6. r语言rank降序_R语言速成之第一章 向量(编辑,排序,10个基本函数)
  7. The Big Bang Theory
  8. 台积电3nm晶圆报价超14万/ 罗永浩AR创业公司获3.6亿融资/ 陶哲轩入驻Mastodon…今日更多新鲜事在此...
  9. python seth什么意思_python中的seth是什么意思
  10. Pandas教程 | 超好用的Groupby用法详解