石家庄住房城乡建设厅网站,宿迁网站建设推广公司,wordpress metaslider,什么是电子商务网站开发概述
模板设计模式#xff08;Template Design Pattern#xff09;是一种行为型设计模式#xff0c;它定义了一个算法的骨架#xff0c;将算法的一些步骤延迟到子类中实现。模板设计模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
模板设计模式的核心思想…概述
模板设计模式Template Design Pattern是一种行为型设计模式它定义了一个算法的骨架将算法的一些步骤延迟到子类中实现。模板设计模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
模板设计模式的核心思想是将一个算法的主要结构定义在一个模板方法中而将具体某些步骤的实现交给子类去完成。
// 模板类 抽象类Beverage--饮料
abstract class Beverage {// 模板方法定义算法的骨架public final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}// 具体步骤由子类实现abstract void brew();abstract void addCondiments();// 公共方法void boilWater() {System.out.println(Boiling water);}void pourInCup() {System.out.println(Pouring into cup);}
}// 具体子类
class Coffee extends Beverage {void brew() {System.out.println(Dripping coffee through filter);}void addCondiments() {System.out.println(Adding sugar and milk);}
}class Tea extends Beverage {void brew() {System.out.println(Steeping the tea);}void addCondiments() {System.out.println(Adding lemon);}
}// 客户端代码
public class TemplateExample {public static void main(String[] args) {Beverage coffee new Coffee();Beverage tea new Tea();System.out.println(Making coffee:);coffee.prepareRecipe();System.out.println(\nMaking tea:);tea.prepareRecipe();}
}
在这个示例中Beverage 是模板类定义了模板方法 prepareRecipe()其中包含了煮水、冲泡、倒入杯子和加调料的步骤。brew() 和 addCondiments() 是具体步骤冲泡和加调料由子类实现。Coffee 和 Tea 是具体子类分别实现了不同的冲泡和调料步骤。
通过模板设计模式模板类 Beverage 提供了一个通用的算法骨架而具体步骤的实现交给子类。这样可以确保算法的结构一致同时允许不同子类根据自身特点进行实现。
使用场景、源码应用
模板设计模式在许多场景下都可以应用特别是在需要定义一组具有共同流程的操作时但每个操作可能有不同的实现细节。以下是一些常见的应用场景 框架和库许多框架和库使用模板设计模式来定义通用的操作流程然后允许用户通过子类来实现特定的操作细节。比如数据库操作框架可以定义一个通用的操作流程然后用户可以通过继承来实现特定数据库的连接和操作。 算法实现在某些算法中有一些步骤是通用的但有些步骤可能因情况而异。模板设计模式允许你将通用的步骤放在模板方法中然后由子类来实现不同的步骤。 工作流程在工作流程管理中可以使用模板设计模式来定义通用的工作流程然后让不同的流程实例来实现具体的任务。 生命周期管理在许多应用中有一些生命周期的操作是通用的例如初始化、清理资源等。模板设计模式可以用于定义这些通用的生命周期操作。
在源码中模板设计模式也有许多应用。以下是一些示例 Java Servlet在 Java Servlet 中HttpServlet 就是一个使用模板设计模式的例子。HttpServlet 定义了 service() 方法作为模板方法然后具体的 HTTP 请求处理由不同的子类来实现。 JUnit 测试框架在 JUnit 中测试用例的执行过程也是一个典型的模板设计模式。JUnit 提供了测试用例的生命周期方法例如 setUp() 和 tearDown()然后用户可以在子类中实现这些方法来执行测试。 Spring Framework在 Spring 中JdbcTemplate 类用于执行数据库操作它将数据库操作的通用流程定义在模板方法中而具体的 SQL 执行由用户提供的回调函数实现。
这些只是一些示例模板设计模式在许多框架和库中都有广泛的应用它提供了一种结构化的方式来定义通用的操作流程并允许具体实现在子类中进行定制。
Java Servlet
对于 Java Web 项目开发来说常用的开发框架是 SpringMVC。利用它我们只需要关注业务代码的编写底层的原理几乎不会涉及。但是如果我们抛开这些高级框架来开发 Web 项目必然会用到 Servlet。实际上使用比较底层的 Servlet 来开发 Web 项目也不难。我们只需要定义一个继承 HttpServlet 的类并且重写其中的 doGet() 或 doPost() 方法来分别处理 get 和 post 请求。具体的代码示例如下所示
public class HelloServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write(Hello World.);}
}除此之外我们还需要在配置文件 web.xml 中做如下配置。Tomcat、Jetty 等 Servlet 容器在启动的时候会自动加载这个配置文件中的 URL 和 Servlet 之间的映射关系。
servletservlet-nameHelloServlet/servlet-nameservlet-classcom.xzg.cd.HelloServlet/servlet-class
/servlet
servlet-mappingservlet-nameHelloServlet/servlet-nameurl-pattern/hello/url-pattern
/servlet-mapping当我们在浏览器中输入网址比如http://127.0.0.1:8080/hello 的时候Servlet 容器会接收到相应的请求并且根据 URL 和 Servlet 之间的映射关系找到相应的 ServletHelloServlet然后执行它的 service() 方法。service() 方法定义在父类 HttpServlet 中它会调用 doGet() 或 doPost() 方法然后输出数据“Hello world”到网页。我们现在来看HttpServlet 的 service() 函数长什么样子。
public 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);
}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 doesnt 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 {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() 方法就是一个模板方法它实现了整个 HTTP 请求的执行流程**doGet()、doPost() 是模板中可以由子类来定制的部分。**实际上这就相当于 Servlet 框架提供了一个扩展点doGet()、doPost() 方法让框架用户在不用修改 Servlet 框架源码的情况下将业务代码通过扩展点镶嵌到框架中执行。
模板模式与Callback回调函数有何区别和联系
联系
共同点两者都涉及将一些逻辑从调用代码中抽离出来使代码更具模块化和可维护性。抽象步骤在模板模式中一个通用的算法框架定义了一系列的抽象步骤子类可以通过实现这些步骤来完成特定的行为。在回调函数中一个函数可以接受一个回调函数作为参数使调用者能够在适当的时候执行这个回调函数完成特定的操作。
区别 角色和目的 模板模式主要目的是在超类中定义算法的骨架而将一些具体步骤的实现推迟到子类中。它更关注整个流程的结构和控制。回调函数主要目的是允许调用者在某个代码块执行时插入自己的代码逻辑。它更关注于将执行权交给外部代码以便根据需要执行回调逻辑。 控制权 模板模式控制权由超类控制子类只实现具体的步骤流程由模板方法决定。回调函数控制权在调用者手中调用者通过提供回调函数来决定在何时执行回调逻辑。 调用关系 模板模式子类通过继承超类来实现抽象步骤超类负责调用子类的方法。回调函数调用者将回调函数作为参数传递给被调用者被调用者在适当的时候调用回调函数。
举例
一个具体的区别和联系示例可以是在GUI编程中比如在按钮被点击时要执行的操作。使用模板模式你可以定义一个通用的按钮点击流程包括按钮的渲染、点击事件的处理等。使用回调函数你可以将点击事件处理的逻辑作为一个回调函数传递给按钮组件以便在按钮被点击时执行。 Java中的 java.util.concurrent 包中的一些类使用了回调来实现多线程编程。例如Executor 接口中的 execute(Runnable command) 方法就接受一个 Runnable 对象作为回调用于在线程池中执行任务。
总之模板模式和回调函数在不同的场景下有不同的应用但都关注于提高代码的模块化和可重用性同时也都涉及到将一些代码逻辑从调用者中分离出来。