「全网最细 + 实战源码案例」设计模式——模板方法模式

embedded/2025/2/8 1:50:49/

核心思想

  • 模板方法模式(Template Method Pattern)是一种行为型设计模式,定义了一个算法的骨架(模板),将某些步骤延迟到子类中实现(在不修改结构的情况下),以避免代码重复,提高代码复用性,保持算法的结构稳定。
  • 核心:
    • 模板方法:在父类中定义一个算法的骨架(即模板方法),其中包含一些抽象方法或钩子方法(hook methods),这些方法由子类实现。
    • 不变部分:算法的整体结构是固定的,由父类控制。
    • 可变部分:算法的某些步骤可以被子类重写,以实现不同的行为。


结构

1. 抽象类(Abstract Class)

  • 定义算法的骨架(模板方法)。
  • 由一个模板方法和若干个基本方法构成。
    • 模板方法:定义算法骨架,按某种顺序调用其包含的基本方法。
    • 基本方法:实现算法各步骤的方法,是模板方法的组成部分,分为三类:
      • 抽象方法:由抽象类声明,具体子类实现。
      • 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以覆盖或继承。
      • 钩子方法:抽象类中已实现,包括用于判断的逻辑方法和需要子类重写的空方法。

2. 具体子类(Concrete Class)

  • 实现抽象类中所定义的抽象方法或钩子方法,是一个顶级逻辑的组成步骤。


现实世界类比

  • 模板方法可用于建造大量房屋。 标准房屋建造方案中可提供几个扩展点, 允许潜在房屋业主调整成品房屋的部分细节。

  • 每个建造步骤 (例如打地基、 建造框架、 建造墙壁和安装水电管线等) 都能进行微调, 这使得成品房屋会略有不同。

适用场景

  1. 算法复用:当多个类有相似的算法结构,只有某些步骤不同时。
  2. 框架设计:框架通常定义算法的股价,而将具体实现留给用户。如何 Spring 中的 JdbcTemplate定义了数据库操作的流程,用户只需实现具体的 SQL 语句。
  3. 工作流设计:定义固定的工作流程,但允许某些步骤自定义。

优缺点

优点:

  1. 代码复用:不变的部分放在子类,避免代码重复。
  2. 提高扩展性:子类通过实现抽象方法或重写钩子方法类扩展算法的某些步骤。
  3. 符合开闭原则:算法整体结构(修改)是封闭的,但具体步骤(扩展)是开放的。

缺点:

  1. 一定程度违反里氏替换原则:子类重写默认步骤后可能无法替代父类。
  2. 缺乏灵活性(相比策略模式):子类必须继承模板。

实现步骤

  1. 分析目标算法, 确定能否将其分解为多个步骤。 从所有子类的角度出发, 考虑哪些步骤能够通用, 哪些步骤各不相同。
  2. 创建抽象基类并声明一个模板方法和代表算法步骤的一系列抽象方法。 在模板方法中根据算法结构依次调用相应步骤。 可用 final最终修饰模板方法以防止子类对其进行重写。
  3. 虽然可将所有步骤全都设为抽象类型, 但默认实现可能会给部分步骤带来好处, 因为子类无需实现那些方法。
  4. 可考虑在算法的关键步骤之间添加钩子。
  5. 为每个算法变体新建一个具体子类, 它必须实现所有的抽象步骤, 也可以重写部分可选步骤。

示例

// 抽象类(定义模板方法和基本方法)
public abstract class AbstractClass {// 模板方法定义public final void cookProcess(){pourOil();heatOil();pourVegetable();pourSauce();fry();}public void pourOil(){System.out.println("倒油");}public void heatOil(){System.out.println("热油");}public abstract void pourVegetable();public abstract void pourSauce();public void fry(){System.out.println("翻炒");}
}// 具体子类——包菜
public class BaoCai extends AbstractClass{@Overridepublic void pourVegetable() {System.out.println("下锅的蔬菜是包菜");}@Overridepublic void pourSauce() {System.out.println("下锅的酱料是辣椒");}
}// 具体子类——菜心
public class CaiXin extends AbstractClass{@Overridepublic void pourVegetable() {System.out.println("下锅的蔬菜是菜心");}@Overridepublic void pourSauce() {System.out.println("下锅的酱料是蒜蓉");}
}// 客户端
public class Client {public static void main(String[] args) {AbstractClass baoCai = new BaoCai();baoCai.cookProcess();System.out.println("---------------------------------------------");AbstractClass caiXin = new CaiXin();caiXin.cookProcess();}
}

在源码中的应用


与其他模式的关系

  • 工厂方法模式是模板方法模式的一种特殊形式。 同时, 可以作为一个大型中的一个步骤。
  • 模板方法基于继承机制: 它允许你通过扩展子类中的部分内容来改变部分算法。 策略模式基于组合机制: 你可以通过对相应行为提供不同的策略来改变对象的部分行为。 模板方法在类层次上运作, 因此它是静态的。 策略在对象层次上运作, 因此允许在运行时切换行为。

http://www.ppmy.cn/embedded/160428.html

相关文章

音频录制一般在什么情况下会选择保存为PCM?什么情况会选择保存为WAV?

在音频开发中,选择保存为 PCM 或 WAV 格式取决于具体的应用场景和需求。以下是两种格式的特点以及适用场景的分析: PCM 格式 特点: 原始音频数据: PCM 是未压缩的原始音频数据,没有任何文件头或元数据。数据直接以二进制形式存储,通常是采样点的值。文件体积较大: 由于…

使用 Docker + Nginx + Certbot 实现自动化管理 SSL 证书

使用 Docker Nginx Certbot 实现自动化管理 SSL 证书 在互联网安全环境日益重要的今天,为站点或应用部署 HTTPS 已经成为一种常态。然而,手动申请并续期证书既繁琐又容易出错。本文将以 Nginx Certbot 为示例,基于 Docker 容器来搭建一个…

ISP代理与住宅代理的区别

代理充当用户和互联网之间的中介,在增强安全性、隐私和可访问性方面提供多种功能。在众多代理类型中,ISP和住宅代理脱颖而出,各自拥有不同的功能和应用程序。 一、ISP代理 ISP代理,俗称Internet服务提供商代理,通过其…

VoIP中常见术语

在 VoIP(Voice over Internet Protocol,基于互联网协议的语音传输)技术中,涉及许多专业术语。以下是常见术语及其含义: 1. 核心协议相关 SIP(Session Initiation Protocol,会话发起协议&#xf…

回溯算法中关于剪枝的一些应用

衔接上篇( ^ _ ^ ) 剪枝优化是回溯算法中一种重要的优化手段,其核心思想是 提前终止无效的递归分支,避免无意义的搜索,从而大幅减少计算量。通过合理剪枝,可以将指数级的时间复杂度降低到更优的水平。 一、…

【数据结构篇】时间复杂度

一.数据结构前言 1.1 数据结构的概念 数据结构(Data Structure)是计算机存储、组织数据的⽅式,指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤,所以我们要学各式各样的数据结构, 如&#xff1a…

洛谷P2638 安全系统

安全系统 题目描述 特斯拉公司的六位密码被轻松破解后,引发了人们对电动车的安全性能的怀疑。李华听闻后,自己设计了一套密码: 假设安全系统中有 n n n 个储存区,每个储存区最多能存储存 2 2 2 种种类不同的信号(…

【Uniapp-Vue3】从uniCloud中获取数据

需要先获取数据库对象: let db uniCloud.database(); 获取数据库中数据的方法: db.collection("数据表名称").get(); 所以就可以得到下面的这个模板: let 函数名 async () > { let res await db.collection("数据表名称…