深入理解设计模式-行为型之模板(和回调区别联系)

这篇具有很好参考价值的文章主要介绍了深入理解设计模式-行为型之模板(和回调区别联系)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

模板设计模式(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 {
    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 

throws ServletException, IOException {
        this.doPost(req, resp);
   }
    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 

throws ServletException, IOException {
        resp.getWriter().write("Hello World.");
   }
}

除此之外,我们还需要在配置文件 web.xml 中做如下配置。Tomcat、Jetty 等 Servlet 容器在启动的时候,会自动加载这个配置文件中的 URL 和 Servlet 之间的映射关系。

<servlet>

    <servlet-name>HelloServlet</servlet-name>

    <servlet-class>com.xzg.cd.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>

    <servlet-name>HelloServlet</servlet-name>

    <url-pattern>/hello</url-pattern>
</servlet-mapping>

当我们在浏览器中输入网址(比如,http://127.0.0.1:8080/hello )的时候,Servlet 容器会接收到相应的请求,并且根据 URL 和 Servlet 之间的映射关系,找到相应的 Servlet(HelloServlet),然后执行它的 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 doesn't support if-modified-since, no reason

            // to go through further expensive logic

            doGet(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 less

                maybeSetLastModified(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 对象作为回调,用于在线程池中执行任务。

总之,模板模式和回调函数在不同的场景下有不同的应用,但都关注于提高代码的模块化和可重用性,同时也都涉及到将一些代码逻辑从调用者中分离出来。文章来源地址https://www.toymoban.com/news/detail-654165.html

到了这里,关于深入理解设计模式-行为型之模板(和回调区别联系)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式(十四):行为型之策略模式

    设计模式系列文章 设计模式(一):创建型之单例模式 设计模式(二、三):创建型之工厂方法和抽象工厂模式 设计模式(四):创建型之原型模式 设计模式(五):创建型之建造者模式 设计模式(六):结构型之代理模式 设计模式(七):结构型之适配器模式 设计模式(八):结构型之装

    2024年02月09日
    浏览(43)
  • 【Java 设计模式】行为型之状态模式

    状态模式(State Pattern)是一种行为型设计模式,用于通过将对象的行为封装到不同的状态类中,使得对象在不同的状态下具有不同的行为。状态模式允许对象在内部状态发生改变时改变其行为,而无需修改其代码。在本文中,我们将深入研究Java中状态模式的定义、结构、使

    2024年01月24日
    浏览(51)
  • 设计模式(二十):行为型之迭代器模式

    设计模式系列文章 设计模式(一):创建型之单例模式 设计模式(二、三):创建型之工厂方法和抽象工厂模式 设计模式(四):创建型之原型模式 设计模式(五):创建型之建造者模式 设计模式(六):结构型之代理模式 设计模式(七):结构型之适配器模式 设计模式(八):结构型之装

    2024年02月09日
    浏览(53)
  • 【Java 设计模式】行为型之命令模式

    命令模式(Command Pattern)是一种行为型设计模式,用于将请求封装为对象,使得可以参数化客户端对象,并且能够排队、记录请求,以及支持撤销操作。在本文中,我们将深入研究Java中命令模式的定义、结构、使用场景以及如何在实际开发中应用。 命令模式是一种行为型设

    2024年01月23日
    浏览(43)
  • 【Java 设计模式】行为型之责任链模式

    责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,用于将请求发送者和接收者解耦,使得多个对象都有机会处理请求。责任链模式通过创建一个处理请求的链,将请求沿着链传递,直到有一个对象能够处理为止。在本文中,我们将深入研究Java中责任链模式的定

    2024年01月24日
    浏览(49)
  • C++设计模式行为型之观察者模式

    一、 概述         观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 二、 示例代码 #include list class Subject; class Observer { public:     virtual ~Observer();     virtual void Update(Subject* theChangedSubject) =

    2024年02月14日
    浏览(44)
  • 设计模式行为型——模板模式

    目录 模板模式的定义 模板模式的实现 模板模式角色 模板模式类图 模板模式举例 模板模式代码实现 模板模式的特点 优点 缺点 使用场景 注意事项 实际应用         模板模式(Template Pattern)属于行为型设计模式,又叫模版方法模式(Template Method Pattern),是指定义一个算法

    2024年02月13日
    浏览(37)
  • 设计模式【行为型】-- 模板方法模式

          模板方法模式是一种行为型设计模式,它定义了一个操作中的算法骨架,将一些步骤的具体实现延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。 模板方法模式基于一个抽象类或接口定义算法的骨架,该骨架由一个模板

    2024年02月16日
    浏览(47)
  • 设计模式(六):模板方法模式(行为型模式)

    Template Method,模板方法:定义一个操作中的算法的骨架,而将一 些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即 可以重定义该算法得某些特定步骤。 举例说明 奶茶制作过程,第一步加牛奶,第二步加糖,第三步加其他配料。第三步对于不同口味的奶

    2024年02月21日
    浏览(45)
  • 【玩转23种Java设计模式】行为型模式篇:模板模式

    软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 汇总目录链接:【玩转23种Java设计模式】学习目录汇总

    2024年02月16日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包