目录

  • 第一章 模板模式介绍
  • 第二章 模板模式实现
    • 2.1、抽象父类
    • 2.2、具体子类
    • 2.3、测试类
  • 第三章 模板模式应用

项目地址:https://gitee.com/caochenlei/design-pattern

第一章 模板模式介绍

模板模式的介绍:

在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。

例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。

这样的例子在生活中还有很多,例如,一个人每天会起床、吃饭、做事、睡觉等,其中“做事”的内容每天可能不同。我们把这些规定了流程或格式的实例定义成模板,允许使用者根据自己的需求去更新它,例如,简历模板、论文模板、Word 中模板文件等。

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

模板模式的优点:

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

模板模式的缺点:

  • 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统的复杂度。
  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
  • 由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。

模板模式的场景:

  • 算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
  • 当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。首先,要识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  • 当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。

模板模式的角色:

抽象父类/抽象模板(Abstract Class): 抽象模板类,负责给出一个算法的轮廓和骨架,它由一个模板方法和若干个基本方法构成。

  • 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
  • 基本方法:是整个算法中的一个步骤,包含以下几种类型。
    • 抽象方法:在抽象类中给出声明,由具体子类实现。
    • 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
    • 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。

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

第二章 模板模式实现

2.1、抽象父类

Game

public abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();//模板public final void play() {//初始化游戏initialize();//开始游戏startPlay();//结束游戏endPlay();}
}

2.2、具体子类

Football

public class Football extends Game {@Overridevoid initialize() {System.out.println("Football Game Initialized.");}@Overridevoid startPlay() {System.out.println("Football Game Started.");}@Overridevoid endPlay() {System.out.println("Football Game Finished.");}
}

Basketball

public class Basketball extends Game {@Overridevoid initialize() {System.out.println("Basketball Game Initialized.");}@Overridevoid startPlay() {System.out.println("Basketball Game Started.");}@Overridevoid endPlay() {System.out.println("Basketball Game Finished.");}
}

2.3、测试类

Client

public class Client {public static void main(String[] args) {Game g1 = new Football();g1.play();Game g2 = new Basketball();g2.play();}
}
Football Game Initialized.
Football Game Started.
Football Game Finished.
Basketball Game Initialized.
Basketball Game Started.
Basketball Game Finished.

第三章 模板模式应用

在 Servlet 中,每一个 Servlet 类都必须要实现 HttpServlet 接口。GenericServlet 是个通用的、不特定于任何协议的 Servlet,它实现了 Servlet 接口。而 HttpServlet 继承于 GenericServlet,为 Servlet 接口提供了处理 HTTP 协议的通用实现,所以我们定义 Servlet 时只需要继承 HttpServlet 即可。

public abstract class HttpServlet extends GenericServlet {//以上代码部分省略...protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{//省略...}protected void doHead(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{//省略...}protected void doPost(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)) {long lastModified = getLastModified(req);if (lastModified == -1) {// servlet doesn't support if-modified-since, no reason// to go through further expensive logicdoGet(req, resp);} else {long ifModifiedSince;try {ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);} catch (IllegalArgumentException iae) {// Invalid date header - proceed as if none was setifModifiedSince = -1;}if (ifModifiedSince < (lastModified / 1000 * 1000)) {// If the servlet mod time is later, call doGet()// Round down to the nearest second for a proper compare// A ifModifiedSince of -1 will always be lessmaybeSetLastModified(resp, lastModified);doGet(req, resp);} else {resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}} else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} 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 {//// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.//String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);}}//以下部分代码省略...
}

在 HttpServlet 的 service 方法中,首先获取请求的方法名,然后根据方法名调用对应的 doXXX 方法,比如说请求方法为 GET,那么就去调用 doGet 方法;请求方法为 POST,那么就去调用 doPost 方法。

这里,HttpServlet 就相当于定义了一套处理 HTTP 请求的模板。service 方法为模板方法,定义了处理 HTTP 请求的基本流程;doXXX 等方法为基本方法,根据请求方法做相应的处理,子类可重写这些方法。HttpServletRequest 中的 Method 则起到钩子方法的作用。

比如实现一个输出 Hello World 的简单 Servlet,代码如下:

public class HelloWorld extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();out.println("<h1>Hello World!</h1>");}
}

设计模式:行为型-模板模式相关推荐

  1. 设计模式 - 行为型 - 模板模式学习

    现象: 设计模式 - 行为型 - 模板模式学习 介绍: 模板模式的设计思路,在抽象类中定义抽象方法的执行顺序, 并将抽象方法设定为只有子类实现,但不提供独立访问的方法 只能通过已经被安排好的定义方法去 ...

  2. 23种设计模式-行为型-模板模式

    定义 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变算法结构的情况下重新定义该算法的某些特定步骤. 主要解决 一些方法通用,却在每一个子类都重写了这一方法. 何时使用 有 ...

  3. Spring中用到的九种设计模式五:模板模式

    系列文章目录 文章目录 系列文章目录 前言 一.模板模式 二.主要角色 1. AbstractTemplate(抽象模板): 2. ConcreteTemplate(具体模板): 三.代码实现与示例 ...

  4. 设计模式行为型-状态模式

    最近学习了设计模式行为型中的状态模式,这个模式的就完全体现出"多态"这种性质了,首先是它的解释:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 为什么说状 ...

  5. 设计模式之——Template模板模式

    Template模式又叫模板模式,是在父类中定义处理流程的框架,在子类中实现具体处理逻辑的模式.当父类的模板方法被调用时程序行为也会不同,但是,不论子类的具体实现如何,处理的流程都会按照父类中所定义的 ...

  6. C语言和设计模式(之模板模式)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 模板对于学习C++的同学,其实并不陌生.函数有模板函数,类也有模板类.那么这个模板模式是个什么 ...

  7. [设计模式-行为型]模板方法模式(Template Method)

    一句话 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. 概括 解析 看过<如何说服女生上床>这部经典文章吗?女生从认识到上床的不变的步骤分为巧遇.打破僵局.展开追求.接吻.前戏.动 ...

  8. 设计模式 - 创建型 - 工厂模式

    2019独角兽企业重金招聘Python工程师标准>>> 介绍 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个产品类,工厂模式使其创建过程延迟到子类进行. 优点: 1.一个 ...

  9. [设计模式-行为型]访问者模式(Vistor)

    一句话 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 概括 解析 情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对 ...

最新文章

  1. 算法导论之贪心算法(Huffman编码和拟阵)
  2. MySQL性能调优的14板斧
  3. 骑士 java_在递归骑士之旅中正确声明变量(Java作业)
  4. 面试题之第一部分(Python基础篇) 80题
  5. java多线程问题 Runnable和Callable有什么不同?
  6. 3d打印主要的切片参数类型_3D打印机切片参数详情说明
  7. 【Julia】Julia使用Pkg下载镜像配置问题解决方案
  8. 围炉听风,新醅试手烫
  9. mysql stmt attr set_mysqli_stmt::attr_set()
  10. SqlServer的基本使用
  11. android 自定义方形章,Android自定义View-圆形印章
  12. java对接 布防 海康威视_java web整合海康威视录像机摄像SDK
  13. 中小企业融资风险分类有哪些
  14. 1645. Hopper Company Queries II
  15. 超好用,18 个 Jupyter Notebook 使用技巧助你快速腾飞
  16. velocity页面js引入#foreach遍历list
  17. proof_LDPC
  18. 产品分享:Qt+OSG教育学科工具之地理三维星球
  19. aba会导致问题_浅谈 ABA 问题
  20. 读书笔记写法--怎么做读书笔记

热门文章

  1. OpenCV找圆系列(2)HoughCircles算子新增了HOUGH_GRADIENT_ALT方法,效果好多了
  2. 新型消防建设-3D可视化消防预案综合管理平台建设方案
  3. 推鉴一本书--人体素描
  4. python判断素数的函数_python寻找1~n以内(包括n)所有素数
  5. mysql barracuda_这可能是把MySQL存储引擎讲解的最清楚的一篇文章了
  6. 第三次自考总结——时间管理和学习知识
  7. 2012年河北职称计算机操作题,2012年河北省职称计算机考试操作题及答案
  8. 苹果Vision Pro物料成本曝光,3499美金售价原来是这样来的
  9. 在DOS下让ISO文件引导系统 实现无光驱安装系统
  10. linux redis自动运行,linux设置自启动redis