设计模式-模板方法

文章目录

  • 前言
  • 模板方法模式简介
  • Java代码示例
  • 模板方法使用场景
  • 模板方法使用场景

前言

当我们需要在一个算法的框架中定义算法的骨架,并将一些步骤的具体实现留给子类来完成时,模板方法模式是一种非常有用的设计模式。这篇博客将介绍模板方法模式的概念,并提供一个简单的Java代码示例来说明如何使用模板方法模式。

模板方法模式简介

模板方法模式是一种行为型设计模式,它定义了一个算法的骨架,将算法中的一些步骤的具体实现延迟到子类中。这种模式有助于在不改变算法整体结构的情况下,允许子类定制算法的特定步骤。

模板方法模式包括以下主要角色:

  1. 抽象类(Abstract Class):定义算法的骨架,包括一个模板方法和一些抽象方法,这些抽象方法由子类来实现。

  2. 具体子类(Concrete Subclass):实现抽象类中的抽象方法,完成算法的具体步骤。

Java代码示例

假设我们正在开发一个咖啡和茶的制作应用程序。制作咖啡和茶的过程有一些共同的步骤,但也有一些特定于每种饮料的步骤。我们可以使用模板方法模式来处理这种情况。

首先,让我们创建一个抽象类 Beverage,它定义了制作饮料的模板方法以及一些抽象方法:

// 抽象类
public abstract class Beverage {// 模板方法,定义了制作饮料的算法骨架public final void prepareBeverage() {boilWater();brew();pourInCup();addCondiments();}// 抽象方法,由子类实现protected abstract void brew();protected abstract void addCondiments();// 共同的步骤private void boilWater() {System.out.println("Boiling water");}private void pourInCup() {System.out.println("Pouring into cup");}
}

接下来,我们可以创建具体的子类,分别表示咖啡和茶,实现它们的特定步骤:

// 具体子类:咖啡
public class Coffee extends Beverage {@Overrideprotected void brew() {System.out.println("Dripping Coffee through filter");}@Overrideprotected void addCondiments() {System.out.println("Adding Sugar and Milk");}
}// 具体子类:茶
public class Tea extends Beverage {@Overrideprotected void brew() {System.out.println("Steeping the tea");}@Overrideprotected void addCondiments() {System.out.println("Adding Lemon");}
}

现在,我们可以在客户端代码中使用这些具体子类来制作咖啡和茶:

public class Main {public static void main(String[] args) {Beverage coffee = new Coffee();Beverage tea = new Tea();System.out.println("Making coffee:");coffee.prepareBeverage();System.out.println("\nMaking tea:");tea.prepareBeverage();}
}

在这个示例中,抽象类 Beverage 定义了制作饮料的模板方法 prepareBeverage,并将一些共同的步骤封装在其中。具体子类 CoffeeTea 分别实现了特定的步骤。客户端代码可以使用这些具体子类来制作不同的饮料,而不需要了解制作的具体步骤。

这个示例展示了模板方法模式的核心思想,即定义算法的骨架,将一些步骤的实现留给子类,从而实现了代码的复用和扩展性。这种模式特别适用于具有共同步骤的算法家族。

模板方法使用场景

模板方法(Template Method)是一种行为型设计模式,它定义了一个算法的骨架,将算法中的一些步骤延迟到子类中实现。这个模式在以下情况下特别有用:

  1. 算法的骨架已经确定,但某些步骤的具体实现可以变化: 当你有一个算法,但其中的一些步骤可以根据不同的情况或需求而变化时,可以使用模板方法。它允许你在超类中定义通用的算法结构,而将特定的实现细节留给子类。

  2. 避免代码重复: 模板方法有助于避免在多个类中复制相似的代码。通过将共享的算法步骤放在超类中,你可以减少代码重复性,并使代码更容易维护。

  3. 确保一致性: 模板方法确保在算法中的每个步骤都以相同的顺序执行。这可以确保算法的行为是一致的,无论哪个子类实现了具体的步骤。

  4. 扩展性: 子类可以轻松地扩展或修改算法的某些部分,而不会影响整体算法结构。这使得代码更容易维护和扩展。

  5. 钩子方法: 模板方法通常包括一个或多个“钩子方法”,这些方法在超类中有默认实现,但子类可以选择性地覆盖它们以改变算法的行为。这种机制允许子类在不影响整个算法结构的情况下自定义部分行为。

  6. 标准化: 模板方法有助于定义一种标准的算法模式,这可以在整个项目或组织中得到复用,从而提高代码的一致性和可维护性。

举例来说,模板方法常常用于编写框架或库,其中定义了一些通用的操作流程,而具体的应用程序可以通过子类化来提供定制化的实现,同时保持整体架构的稳定性。一个经典的例子是Java中的Servlet生命周期方法,其中doGet()和doPost()等方法是模板方法,由开发者根据具体需求来实现。

模板方法使用场景

模板方法模式是一种常用的设计模式,通常在以下情况下使用:

  1. 算法的骨架已经确定,但某些步骤的具体实现可以变化: 当你有一个算法,但其中的一些步骤可以根据不同的情况或需求而变化时,可以使用模板方法。它允许你在超类中定义通用的算法结构,而将特定的实现细节留给子类。

  2. 避免代码重复: 模板方法有助于避免在多个类中复制相似的代码。通过将共享的算法步骤放在超类中,你可以减少代码重复性,并使代码更容易维护。

  3. 确保一致性: 模板方法确保在算法中的每个步骤都以相同的顺序执行。这可以确保算法的行为是一致的,无论哪个子类实现了具体的步骤。

  4. 扩展性: 子类可以轻松地扩展或修改算法的某些部分,而不会影响整体算法结构。这使得代码更容易维护和扩展。

  5. 钩子方法: 模板方法通常包括一个或多个“钩子方法”,这些方法在超类中有默认实现,但子类可以选择性地覆盖它们以改变算法的行为。这种机制允许子类在不影响整个算法结构的情况下自定义部分行为。

  6. 标准化: 模板方法有助于定义一种标准的算法模式,这可以在整个项目或组织中得到复用,从而提高代码的一致性和可维护性。

具体的使用场景包括但不限于:

  • 图形界面应用程序中的窗口、对话框等构建: 不同类型的窗口或对话框可能具有相似的构建步骤,但具体实现可能不同。

  • 数据访问层的实现: 在数据库访问中,可以定义一个通用的数据访问方法,但具体的 SQL 查询或 NoSQL 操作可以在子类中实现。

  • 游戏开发中的游戏角色: 游戏中的不同角色可能共享某些行为,但具有不同的特殊技能或动作。

  • 文档生成工具: 在文档生成工具中,可以定义一个通用的文档生成算法,但具体的文档格式或输出方式可以由子类定义。

总之,模板方法模式在任何需要定义算法骨架并允许子类提供特定实现的情况下都是有用的。它有助于提高代码的复用性、可维护性和可扩展性。

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

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

相关文章

将 ChatGPT 用于数据科学项目的指南

推荐:使用 NSDT场景编辑器 快速搭建3D应用场景 我们都知道 ChatGPT 的受欢迎程度以及人们如何使用它来提高生产力。但是,如果您是新手,则值得注册ChatGPT免费演示并尝试它所能做的一切。您还应该参加我们的 ChatGPT 简介课程,学习…

199. 二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,null,3] 输出: [1,3]示例 3: 输入: [] 输出: []提示: 二…

Mixin从理论到实践

mixin从理论到实践 mixin从理论到实践一、什么是mixin二、使用mixin三、mixin的合并策略四、mixin辨析五、个人实践 mixin从理论到实践 一、什么是mixin mixin混入 — Vue.js (vuejs.org) 官方解释: 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue …

产品波士顿矩阵

随着公司产品的增多,每个产品的生命周期节点各不相同,很多时候我们往往在产品结构、资源分配方面会产生各种问题,导致需要发展的产品得不到资源,消耗资源的产品却有无法增长,所谓不聚焦导致的问题其实是资源和发展错配…

ESP32蓝牙实例-BLE服务器与客户端通信

BLE服务器与客户端通信 文章目录 BLE服务器与客户端通信1、软件准备2、硬件准备3、代码实现3.1 BLE服务器实现3.2 Android手机测试BLE服务器3.3 ESP32 BLE客户端在本文中,我们将介绍如何使用低功耗蓝牙在两个 ESP32 开发板之间执行 BLE 服务器客户端通信。 换句话说,将介绍如…

Sphinx 找不到 Doxygen 导出的 xml 中的内容的解决方法

Sphinx Breathe Doxygen CMake 的教程看这个就够了 https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/ 但是他还是少写了一些东西,所以还是有一些小坑的 这些坑会导致 Sphinx 找不到 Doxygen 导出…

使用 PHP WorkerMan 构建 WebSocket 全双工群聊通信(二)

在很早很早以前,WebSocket 协议还没有被发明的时候,人们在 Web 端制作类实时数据动态更新时,一般采用轮询、 长连接 (Long Polling) 来实现。大概就是: 轮询:客户端不停发送 HTTP 请求给服务端,服务端返回…

在阿里云 linux 服务器上查看当前服务器的Nginx配置信息

我们可以通过命令 sudo nginx -t查看到nginx.conf的路径 可以通过 sudo nginx -T查看 nginx 详细配置信息,包括加载的配置文件和配置块的内容 其中也会包括配置文件的内容

环境扫描/透射电子显微镜气体样品架的真空压力和微小流量控制解决方案

摘要:针对环境扫描/透射电子显微镜对样品杆中的真空压力气氛环境和流体流量精密控制控制要求,本文提出了更简单高效和准确的国产化解决方案。解决方案的关键是采用动态平衡法控制真空压力,真空压力控制范围为1E-03Pa~0.7MPa;采用压…

git 合并分支某次(commit)提交

需求:将develop分支某次提交合并到master上面,其他修改不同步; //切换到master分支 git checkout master //查看develop分支提交记录,获取对应记录哈希值; git log develop // 按上下按钮可以上下查询对应记录&#xf…

typeScript--[接口interface的继承]

和类一样,接口也可以通过关键字 extents 相互继承。接口继承,分为:单继承和多继承,即继承多个接口。另外,接口也可以继承类,它会继承类的成员,但不包括具体的实现,只会把类的成员作为…

DevOps到底是什么意思?

前言: 当我们谈到 DevOps 时,可能讨论的是:流程和管理,运维和自动化,架构和服务,以及文化和组织等等概念。那么,到底什么是"DevOps"呢? 那么,DevOps是什么呢? 有人说它是一种方法,也有人说它是一种工具,还有人说它是一种思想。更有甚者,说它是一种哲学…

读高性能MySQL(第4版)笔记06_优化数据类型(上)

1. 良好的逻辑设计和物理设计是高性能的基石 1.1. 反范式的schema可以加速某些类型的查询,但同时可能减慢其他类型的查询 1.2. 添加计数器和汇总表是一个优化查询的好方法,但它们的维护成本可能很 1.3. 将修改schema作为一个常见事件来规划 2. 让事情…

仅做笔记用:Stable Diffusion 通过 ControlNet 扩展图片 / 扩图

发觉之前的 Outpainting 脚本效果仍旧不是很理想。这里又找了一下有没有效果更好的途径来扩图。于是就找到了通过 ControlNet 的方式来实现效果更好的扩图。这里临时记录一下在 Stable Diffusion 怎么使用 ControlNet 来扩展图片。 下载 control_v11p_sd15_inpaint_fp16.safet…

【源码】JavaWeb+Mysql招聘管理系统 课设

简介 用idea和eclipse都可以&#xff0c;数据库是mysql&#xff0c;这是一个Java和mysql做的web系统&#xff0c;用于期末课设作业 cout<<"如果需要的小伙伴可以http://www.codeying.top";可定做课设 线上招聘平台整合了各种就业指导资源&#xff0c;通过了…

Android获取系统读取权限

在Androidifest.xml文件中加上授权语句 <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/>

Git 概述命令、idea中的使用

目录 Git概述 Git代码托管服务 Git常用命令 Git 全局设置 获取 Git 仓库 ​编辑Git 工作区中文件的状态 本地仓库操作 远程仓库操作 ​编辑分支操作 标签操作 在IDEA中使用Git 1.获取Git仓库 .gitignore 表示忽略 2.本地仓库操作 3.远程仓库操作 4.分支操作 Git是…

C++设计模式-更新中

单例模式 这个类实现了单例模式。单例模式是一种设计模式&#xff0c;旨在确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。 在 ConnectionManager 类中&#xff0c;它通过以下方式实现了单例模式&#xff1a; 构造函数 ConnectionManager() 被声明为…

c++qt day2

封装一个结构体&#xff0c;结构体中包含一个私有数组&#xff0c;用来存放学生的成绩&#xff0c;包含一个私有变量&#xff0c;用来记录学生个数&#xff0c; 提供一个公有成员函数&#xff0c;void setNum(int num)用于设置学生个数 提供一个公有成员函数&#xff1a;void…

Spring Boot跨域问题简介

什么是跨域问题&#xff1f; 在Web开发中&#xff0c;跨域指的是在浏览器中访问一个不同于当前域名的资源。浏览器出于安全考虑&#xff0c;限制了这种跨域资源的访问。具体来说&#xff0c;当浏览器使用XMLHttpRequest或Fetch API发送跨域请求时&#xff0c;目标服务器必须在…