模板方法设计模式理论与应用

简介: 首先了解一下什么是模板,在工厂中指定某一样工具的时候,会先设计一个模子,然后就根据这个模子制造成各种颜色的工具。虽然制造出来的工具可能样式、颜色都不同,但是基本的样子和模子是一模一样。抽象到编程中,我们设计一个抽象类模板,指定代码的执行流程,后续子类实现各自的代码逻辑,但是执行流程和抽象父类一样,这种设计模式就是模板方法模式。

听说微信搜索《Java鱼仔》会变更强哦!


本文收录于githubgitee ,里面有我完整的Java系列文章,学习或面试都可以看看哦


(一)什么是模板方法模式(Template method)


首先了解一下什么是模板,在工厂中指定某一样工具的时候,会先设计一个模子,然后就根据这个模子制造成各种颜色的工具。虽然制造出来的工具可能样式、颜色都不同,但是基本的样子和模子是一模一样。


抽象到编程中,我们设计一个抽象类模板,指定代码的执行流程,后续子类实现各自的代码逻辑,但是执行流程和抽象父类一样,这种设计模式就是模板方法模式


(二)模板方法模式中的角色


abstractClass:抽象类


抽象类角色就是上面说的模子,该角色中需要定义抽象方法以及方法执行流程,这些抽象方法由concreteClass具体类实现


concreteClass:具体类


具体类需要继承抽象类,并实现抽象类中的抽象方法,这里实现的方法将会在执行流程中被调用。


(三)代码案例


接下来展示Template method的代码案例。在这段代码中,我会先写一个抽象类,内容是打开冰箱放东西的三大步骤;接着写两个具体类,分别是放水果和放大象。


首先是抽象类:AbstractRefrigerator


publicabstractclassAbstractRefrigerator {
publicabstractvoidopenDoor();
publicabstractvoidputSomething();
publicabstractvoidcloseDoor();
publicfinalvoidexecute(){
openDoor();
putSomething();
closeDoor();
    }
}

在抽象类中,定义了三个抽象方法,分别是打开冰箱门、放入一些东西、关上冰箱门。接着定义一个execute模板方法,指定模板的方法执行流程。 创建第一个具体类PutFruit:

publicclassPutFruitextendsAbstractRefrigerator {
privateStringfruitName;
publicPutFruit(StringfruitName){
this.fruitName=fruitName;
    }
@OverridepublicvoidopenDoor() {
System.out.println("打开冰箱门");
    }
@OverridepublicvoidputSomething() {
System.out.println("放入"+fruitName);
    }
@OverridepublicvoidcloseDoor() {
System.out.println("关上冰箱门");
    }
}

在第一个具体类中,继承了统一的抽象类,并实现三个抽象方法。 创建第二个具体类:PutElephant:

publicclassPutElephantextendsAbstractRefrigerator {
@OverridepublicvoidopenDoor() {
System.out.println("打开冰箱门");
    }
@OverridepublicvoidputSomething() {
System.out.println("放入大象");
    }
@OverridepublicvoidcloseDoor() {
System.out.println("关上冰箱门");
    }
}

最后在main方法中使用两个具体类:

publicclassMain {
publicstaticvoidmain(String[] args) {
AbstractRefrigeratora1=newPutFruit("apple");
a1.execute();
AbstractRefrigeratora2=newPutElephant();
a2.execute();
    }
}

上述每个具体类中都有自己的实现,但是最后执行流程都是按照抽象类中指定的模板规则,这就是模板方法设计模式。


(四)在项目中的应用


我翻了一下目前自己写的项目以及工作中写的项目,发现有一个项目中很巧妙的运用了模板设计模式。因为是工作中的项目,我不会贴代码,讲一下应用场景:


这个项目依赖ES进行数据的查询采集,然后对数据做一些操作加工后返回。这里有一套很规范对模板流程:前置查询参数校验->ES查询->查询后结果处理->封装结果返回


这里的一套流程就被做成了一个抽象类赋予了默认对实现,并提供了一个模板方法按顺序执行上述步骤。后续有新的接口需求就直接按照这套模板流程来。


(五)模板方法模式在源码中的应用


javax.servlet.http.HttpServlet类的实现就使用了模板方法模式。HttpServlet中定义了doGet、doHead、doPost、doPut、doDelete、doOptions、doTrace等方法,并定义了service这个模板方法:


publicabstractclassHttpServletextendsGenericServlet {
protectedvoiddoGet(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoiddoHead(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoiddoPost(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoiddoPut(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoiddoDelete(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoiddoOptions(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoiddoTrace(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//...    }
protectedvoidservice(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
Stringmethod=req.getMethod();
longlastModified;
if (method.equals("GET")) {
lastModified=this.getLastModified(req);
if (lastModified==-1L) {
this.doGet(req, resp);
            } else {
longifModifiedSince;
try {
ifModifiedSince=req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentExceptionvar9) {
ifModifiedSince=-1L;
                }
if (ifModifiedSince<lastModified/1000L*1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
                } else {
resp.setStatus(304);
                }
            }
        } elseif (method.equals("HEAD")) {
lastModified=this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
        } elseif (method.equals("POST")) {
this.doPost(req, resp);
        } elseif (method.equals("PUT")) {
this.doPut(req, resp);
        } elseif (method.equals("DELETE")) {
this.doDelete(req, resp);
        } elseif (method.equals("OPTIONS")) {
this.doOptions(req, resp);
        } elseif (method.equals("TRACE")) {
this.doTrace(req, resp);
        } else {
StringerrMsg=lStrings.getString("http.method_not_implemented");
Object[] errArgs=newObject[]{method};
errMsg=MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
        }
    }
}

(六)总结


模板方法设计模式有助于让我们理解抽象类在编程中的含义,其实对很多人而言知道抽象类是什么,但是不理解为什么要使用抽象类。模板方法设计模型就是很好的案例。

相关文章
|
1月前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
1月前
|
设计模式 算法 Java
Java一分钟之-设计模式:策略模式与模板方法
【5月更文挑战第17天】本文介绍了策略模式和模板方法模式,两种行为设计模式用于处理算法变化和代码复用。策略模式封装不同算法,允许客户独立于具体策略进行选择,但需注意选择复杂度和过度设计。模板方法模式定义算法骨架,延迟部分步骤给子类实现,但过度抽象或滥用继承可能导致问题。代码示例展示了两种模式的应用。根据场景选择合适模式,以保持代码清晰和可维护。
31 1
|
1月前
|
设计模式 XML Java
第五篇 设计模式的选择和应用 - 智慧选择与合理实践
第五篇 设计模式的选择和应用 - 智慧选择与合理实践
|
4天前
|
设计模式 数据库连接 PHP
PHP中的面向对象编程与设计模式应用
传统的PHP编程模式在面向对象的趋势下逐渐演进,本文探讨了面向对象编程在PHP中的应用,并深入分析了常用的设计模式如何优化代码结构和可维护性。
|
1天前
|
设计模式 缓存 前端开发
现代PHP开发中的设计模式应用与性能优化
本篇文章深入探讨了PHP开发中设计模式的实际应用及其对性能的影响。通过分析具体案例和最新研究成果,文章揭示了合理运用设计模式不仅可以提升代码的可维护性和扩展性,还能在特定场景下优化性能。我们将一起探索如何通过科学方法将设计模式融入日常开发实践,同时保持代码的高效执行。
|
5天前
|
设计模式 算法
模板方法-大话设计模式
模板方法-大话设计模式
6 0
|
30天前
|
设计模式 开发框架 算法
C++中的设计模式:基本概念与应用
C++中的设计模式:基本概念与应用
29 2
|
11天前
|
设计模式 人工智能 自然语言处理
【设计模式】MVVM模式在AI大模型领域的创新应用
【设计模式】MVVM模式在AI大模型领域的创新应用
21 0
|
15天前
|
设计模式 PHP 开发者
PHP中的设计模式及其应用
在现代软件开发中,设计模式是一种被广泛采纳的方法论,能够帮助开发者解决常见的设计问题并提高代码的灵活性和可维护性。本文将深入探讨PHP中几种常用的设计模式,包括工厂模式、单例模式和观察者模式,分析它们的实现方式以及在实际项目中的应用场景,帮助读者理解和运用这些模式来优化自己的PHP代码设计。
|
1月前
|
设计模式 缓存
理解并应用设计模式在软件开发中的重要性
【5月更文挑战第20天】设计模式是软件开发中的最佳实践,用于解决常见设计问题,提高代码可读性、可维护性、可扩展性和灵活性。本文介绍了为何需要设计模式(如管理依赖、增强可重用性、设计易扩展系统)以及常见的设计模式:工厂模式(封装对象创建)、单例模式(确保类唯一实例)、观察者模式(事件驱动)和适配器模式(解决接口不兼容)。应用设计模式的关键步骤包括识别问题、选择模式、实现模式及测试优化。设计模式对于提升代码质量和降低系统风险至关重要。