23种设计模式 - 模板方法模式

1. 认识模板方法模式

1.1 模式定义

定义一个操作算法中的框架,而将这些步骤延迟加载到子类中。

它的本质就是固定算法框架。

1.2 解决何种问题

让父类控制子类方法的调用顺序

模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

1.3 模式好处

开发人员在开发时,只需要考虑方法的实现。不需要考虑方法在何种情况下被调用。实现代码复用。

1.4 模式适合场景
  • 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
  • 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

2. 模式结构与实例讲解

2.1模式结构

模板方法模式结构图


如模板方法模式结构图所知,有两个类:

  • AblstractClass(抽象类):在抽象类中定义了一系列的操作PrimitiveOperation,每个操作可以使具体的,也可以是抽象的,每个操作对应一个算法的步骤,在子类中可以重新定义或实现这些步骤。TmplateMethod()这个方法用于定义一个算法结构,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
  • ConcreteClass(具体子类):用于实现在父类中声明的抽象基本操作,也可以覆盖在父类中已经实现的具体基本操作。
2.2 实例讲解

创建一个抽象模板结构(AblstractClass)好父亲

public abstract class AblstractClass {//模板方法用来控制子类的顺序 要想有人生必须按老爸的人生顺序来  //声明final不让子类覆盖这个方法,防止改变人生顺序public final void 人生(){学习();工作();爱情();}//家里穷更得用工学习public void 学习(){System.out.println("每天晚上趴在邻居窗上学习");}//工作必须稳定public void 工作(){       System.out.println("从一而终");}//恋爱自由  让儿子自由恋去public abstract void 爱情();}

创建一个具体模板(ConcreteClass)好儿子

public class ConcreteClass extends AblstractClass {//儿子不认可父亲的学习方法  考高分影响同学关系@Overridepublic void 学习() {System.out.println("60分万岁...");}//父亲给我爱情自由  一定好好谈恋爱@Overridepublic void 爱情() {System.out.println("肤白貌美大长腿...");}}

调用他们的人生

public class TestMain {public static void main(String[] args) {ConcreteClass cs  = new ConcreteClass();cs.人生();}}

结果输出

60分万岁...
从一而终
肤白貌美大长腿...

3. 模式在Servlet中的应用

3.1 自己实现一下

浏览器向服务端发送一个请求,常用请求方式有两种,get请求和post请求,这两种请求方式会导致请求参数在请求协议包(Http包)中的位置是不一样的,那么请求协议包中不同的内容到达服务端之后会有不同的对象进行处理,如请求头的内容由tomcat负责,请求体中的内容由request负责,所以此时,开发人员在拿到service()方法后考虑到它可以接受所有请求方式,因此会针对不同的请求方式封装不同的请求方法。

建一个OneServlet 继承GenericServlet,实现service()方法,需要重写里面的doPost和doGet方法。

public class OneServlet extends GenericServlet {@Overridepublic void service(ServletRequest req, ServletResponse arg1) throws ServletException, IOException {//1.从协议包【请求行】中来读取浏览器发送的请求方式HttpServletRequest request = (HttpServletRequest)req;//一般来说由父类修饰的对象由子类来修饰对象,目的就是功能扩充String method = request.getMethod();//POST  GETif("GET".equals(method)){doGet(req, arg1);}else if("POST".equals(method)){doPost(req, arg1);}    }//处理浏览器发送的post请求public void doPost(ServletRequest arg0, ServletResponse arg1){//这里面是doPost封装好的方法System.out.println("doPost is run....");}//处理浏览器发送的get请求public void doGet(ServletRequest arg0, ServletResponse arg1){//这里面是doPost封装好的方法System.out.println("doGet is run....");}}

现在开发人员面临的是,即需要做方法的实现,有需要考虑service()方法在何时调用。在实际开发过程中service()方法里面是一段重复性的代码,所有的servlet类实现中都需要写这么一段重复性的代码,这样重复的开发既增加工作量,又显得代码臃肿,降低了系统耦合度。模板方法设计模式就是来解决这个问题的。下面看一下怎么解决。

建立MyHttpServlet类(就是模板方法设计模式中的父类),继承GenericServlet类。

public  class MyHttpServlet extends GenericServlet {@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {//控制子类中的doGet和doPost方法//1.从协议包【请求行】来读取浏览器发送的请求方式HttpServletRequest request = (HttpServletRequest)req;String method = request.getMethod();//POST  GETif("GET".equals(method)){doGet(req, res);//this.doGet()}else if("POST".equals(method)){doPost(req, res);}}public  void doPost(ServletRequest arg0, ServletResponse arg1){}public void doGet(ServletRequest arg0, ServletResponse arg1){}}

建立TwoServlet类,此时此刻开发人员不用去考虑何时调用doGet方法。当调用TwoServlet类的时候,tomcat一定是调用它的service()方法。

/*** Servlet implementation class TwoServlet*/
public class TwoServlet extends MyHttpServlet {//选择是接受doGet方法还是doPost方法@Overridepublic void doGet(ServletRequest arg0, ServletResponse arg1) {System.out.println("ThreeServlet doGet is run...");}}

测试代码localhost:8080/.../...

ThreeServlet doGet is run...

3.2 看HttpServlet源码

HttpServlet也是继承了GenericServlet ,跟踪找到Service()方法,发现有两个service()方法。

    //这个方法是从它的父类GenericServlet继承过来的@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException{   HttpServletRequest  request;HttpServletResponse response;if (!(req instanceof HttpServletRequest &&res instanceof HttpServletResponse)) {throw new ServletException("non-HTTP request or response");}//分别对请求对象和响应对象做了类型强转。request = (HttpServletRequest) req;response = (HttpServletResponse) res;service(request, response);//调用的是自己声明的service方法,重载。}
}

进入到自己声明的service()方法

  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 = req.getDateHeader(HEADER_IFMODSINCE);if (ifModifiedSince < lastModified) {// 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);}}

发现service方法没有使用final,这是因为如果使用final修饰,就彻底断绝了我们下游开发人员的开发,这样是降低了系统的灵活度。

设计模式是问题解决思想(办法),没有固定的命令搭配 。
如果我们自己可以有这样一些解决办法,那就是好的设计模式。

使用场景: tomcat中,生命周期中触发事件后,变更事件状态和相应动作处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140509.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

发明专利申请费用是多少

一、申请发明专利的费用是多少 1、申请费&#xff1a; 申请费950元(含印刷费50元) 2、审查费 该项费用仅当申请发明专利时缴纳&#xff0c;申请实用新型及外观设计时不用缴纳。 发明申请审查费2500元 3、专利登记费 申请人在接到专利授权通知书和办理登记手续通知书后&a…

卡尔曼家族从零解剖-(06)一维卡尔曼滤波编程实践

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…

【工具】Java计算图片相似度

【工具】Java图片相似度匹配工具 方案一 通过像素点去匹配 /*** * param file1Url 图片url* param file2Url 图片url* return*/public static double img相似度Url(String file1Url, String file2Url){InputStream inputStream1 HttpUtil.createGet(file1Url).execute().…

Unity中Shader光照探针的支持

文章目录 前言一、光照探针用在哪怎么用1、光照探针的应用场景2、我们按照以上条件&#xff0c;在Unity中搭建一个相同的环境3、创建光照探针 二、在我们自己的Shader中&#xff0c;实现支持光照探针1、使用常用的 cginc2、在 v2f 中&#xff0c;准备如下变量3、在顶点着色器中…

macOS文本编辑器 BBEdit 最新 for mac

BBEdit是一款功能强大的文本编辑器&#xff0c;适用于Mac操作系统。它由Bare Bones Software开发&#xff0c;旨在为开发者和写作人员提供专业级的文本编辑工具。 以下是BBEdit的一些主要特点和功能&#xff1a; 多语言支持&#xff1a;BBEdit支持多种编程语言和标记语言&…

ZYNQ PS端的Cache问题

Zynq Cache问题的解决方法 - Kevin_HeYongyuan - 博客园 (cnblogs.com) zynq双核AMP实验之cpu1唤醒代码_xil_settlbattributes-CSDN博客 内存与cache一致性问题_ddr cache一致性-CSDN博客 使用Xil_SetTlbAttributes(0xFFFF0000,0x14de2);可以禁用掉0x1F00 0000区域的Cache&…

负债1320万美元的【思宏集团/Neo-Concep】申请900万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于香港的思宏集团Neo-Concept International Group Holdings Limited(简称&#xff1a;思宏集团&#xff09;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c…

【解刊】IEEE(trans),中科院2区,顶刊,CCF-A类,圈外人别想投?

计算机类 • 好刊解读 今天小编带来IEEE旗下计算机领域好刊的解读&#xff0c;如有相关领域作者有意向投稿&#xff0c;可作为重点关注&#xff01;后文有真实发表案例&#xff0c;供您投稿参考~ 01 期刊简介 IEEE Transactions on Computers ☑️出版社&#xff1a;IEEE …

layui 表格(table)合计 取整数

第一步 开启合计行 是否开启合计行区域 table.render({elem: #myTable, url: ../baidui/, page: true, cellMinWidth: 100,totalRow:true,cols: [[ //表头//{ type: checkbox },{ type: checkbox,totalRowText: "合计" },//合计行区域{ field: id, align: center,…

devops步骤 -- jenkins安装

安装的docker-compose ##安装步骤参考&#xff1a; https://editor.csdn.net/md/?articleId133070011 编写docker-compose.yml version: 3 services: # 集合docker_jenkins:user: root # 为了避免一些…

Zookeeper篇---第八篇

系列文章目录 文章目录 系列文章目录一、描述一下 ZAB 协议二、ZAB 和 Paxos 算法的联系与区别?三、ZooKeeper 宕机如何处理?一、描述一下 ZAB 协议 ZAB 协议是 ZooKeeper 自己定义的协议,全名 ZooKeeper 原子广播协议。 ZAB 协议有两种模式:Leader 节点崩溃了如何恢复和消…

稀疏数组如何帮助我们节省内存,提升性能

本文由葡萄城技术团队发布。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 什么是稀疏矩阵 稀疏矩阵是指矩阵中大部分元素为零的矩阵。在实际应用中&#xff0c;很多矩阵都是稀疏的&#xff0c…

RocketMQ 如何保证消息正常【投递】和【消费】

消息整体处理过程&#xff0c;这里我们将消息的整体处理阶段分为3个阶段进行分析&#xff1a;1、Producer发送消息阶段。 2、Broker处理消息阶段。 3、Consumer消费消息阶段。一、Producer发送消息阶段 1、安全机制保障1&#xff0c;发送方式。 1、同步发送 2、异步发送 3、O…

JPA Buddy快速创建update、find、count、delete、exists方法

JPA Buddy快速创建update、find、count、delete、exists方法&#xff0c;JPA默认提供的CrudRepository\JpaRepository提供的方法比较少&#xff0c;一般我们会手写一些方法&#xff0c;这里我们选择通过JPA Buddy快速生成&#xff0c;之前文章中讲到了JPA Buddy原本是IDEA收费插…

《QT从基础到进阶·二十一》QGraphicsView、QGraphicsScene和QGraphicsItem坐标关系和应用

前言&#xff1a; 我们需要先由一个 QGraphicsView&#xff0c;这个是UI显示的地方&#xff0c;也就是装满可见原色的Scene&#xff0c;然后需要一个QGraphicsScene 用来管理所有可见的界面元素&#xff0c;要实现UI功能&#xff0c;我们需要用各种从QGraphicsItem拼装成UI控件…

scDrug:从scRNA-seq到药物反应预测

scRNA-seq技术允许在转录组水平上对数千个细胞进行测量。scRNA-seq正在成为研究肿瘤微环境中细胞成分及其相互作用的重要工具。scRNA-seq也被用于揭示肿瘤微环境模式与临床结果之间的关联&#xff0c;并在复杂组织中剖析药物治疗的细胞特异性效应。scRNA-seq的最新进展推动了疾…

广告业展示服务预约小程序的效果如何

虽然不少人不会与广告业直接接触&#xff0c;但各种形式的广告却是充斥在人们生活中&#xff0c;线下的传单展板、线上的视频、音频、图文等都是广告很好的传播通道&#xff0c;同时广告业能扩展的客户属性也非常广&#xff0c;下到超市小摊&#xff0c;上到企业公司都有大小相…

RHCE第三次作业

网站需求&#xff1a; 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! [rootserver conf.d]# mkdir /www/openlab [rootserver conf.d]# echo welcome to openlab!!! > /www/openlab/index.html [rootserver openlab]# cat /etc/httpd/conf.d/myhos…

从0到0.01入门React | 006.精选 React 面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

阿里云国际站服务器如何升级内存容量?

阿里云服务器是阿里云供给的计算服务&#xff0c;它具有高效安稳、可扩展性强等特色&#xff0c;适用于各种应用环境。在运用阿里云服务器的过程中&#xff0c;或许会遇到内存容量缺乏的状况&#xff0c;这时候就需求晋级内存容量。那么&#xff0c;阿里云服务器怎么晋级内存容…