当前位置: 首页 > news >正文

设计模式 22 模板方法模式

设计模式 22

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • 设计模式 22
    • 模板方法模式(Template Method Pattern)
      • 1 定义
      • 2 结构
      • 3 示例代码
      • 4 特点
      • 5 适用场景
      • 6 总结

模板方法模式(Template Method Pattern)

1 定义

模板方法模式通过在基类中定义一个模板方法,该方法封装了一个算法的固定步骤,然后允许子类实现或重写这些步骤。这样,子类可以定制算法的具体行为,而无需改变算法的整体结构。

2 结构

模板方法模式包含以下角色:

  • 抽象类(AbstractClass): 定义模板方法和算法的骨架。模板方法按照固定的步骤调用抽象方法或具体方法。
  • 具体类(ConcreteClass): 继承自抽象类,实现或重写抽象方法,定义算法的具体步骤。

UML 类图

+---------------------------+     
|  AbstractClass            |     
+---------------------------+     
| + TemplateMethod(): void  |     
| + Step1(): void           |     
| + Step2(): void           |     
| - Step3(): void           |     
+---------------------------+     ^     |     
+-------------------+     
|  ConcreteClass    |     
+-------------------+     
| - Step3(): void   |     
+-------------------+

3 示例代码

假设我们要制作一杯饮料,制作的过程包括煮水、冲泡、倒入杯中、添加配料等步骤。咖啡和茶是两种不同的饮料,它们在制作过程中的步骤基本相同,但在某些步骤上有所不同。我们可以使用模板方法模式来实现这个场景。

抽象类

// 抽象类 - 饮料制作过程
public abstract class Beverage
{// 模板方法public void PrepareRecipe(){BoilWater();Brew();PourInCup();AddCondiments();}// 具体方法 - 煮水private void BoilWater(){Console.WriteLine("Boiling water");}// 抽象方法 - 冲泡protected abstract void Brew();// 具体方法 - 倒入杯中private void PourInCup(){Console.WriteLine("Pouring into cup");}// 抽象方法 - 添加配料protected abstract void AddCondiments();
}

具体类

// 具体类 - 茶
public class Tea : Beverage
{protected override void Brew(){Console.WriteLine("Steeping the tea");}protected override void AddCondiments(){Console.WriteLine("Adding lemon");}
}// 具体类 - 咖啡
public class Coffee : Beverage
{protected override void Brew(){Console.WriteLine("Dripping coffee through filter");}protected override void AddCondiments(){Console.WriteLine("Adding sugar and milk");}
}

客户端代码

class Program
{static void Main(string[] args){Beverage tea = new Tea();tea.PrepareRecipe();  // 制作茶Console.WriteLine();Beverage coffee = new Coffee();coffee.PrepareRecipe();  // 制作咖啡}
}

运行结果

Boiling water
Steeping the tea
Pouring into cup
Adding lemonBoiling water
Dripping coffee through filter
Pouring into cup
Adding sugar and milk

在这个例子中,Beverage 是抽象类,定义了一个模板方法 PrepareRecipe(),它包含了制作饮料的固定步骤。这些步骤中,有些是具体实现的(如 BoilWater()PourInCup()),而有些是抽象方法,由子类 TeaCoffee 来实现(如 Brew()AddCondiments())。客户端代码可以使用不同的具体类来制作不同的饮料,而不需要关心具体的实现细节。

4 特点

  • 优点:

    • 代码复用: 将通用的算法步骤封装到基类中,子类只需要实现差异化的部分,减少了重复代码。

    • 扩展性强: 子类可以根据需要重写或扩展某些步骤,增加算法的灵活性。

    • 控制算法结构: 父类定义了算法的骨架,确保了算法的整体结构不被子类破坏。

  • 缺点:

    • 增加代码复杂性: 由于引入了继承关系和抽象方法,可能会使代码结构变得复杂。

    • 对子类的依赖: 父类依赖子类来实现某些步骤,可能导致子类必须实现某些方法,即使这些方法在特定情况下并不需要。

5 适用场景

  • 多个类有相似的操作步骤: 当多个类的操作步骤大致相同时,可以使用模板方法模式将相同的部分提取到抽象类中。
  • 算法需要多个步骤: 当算法需要分解为多个步骤,并且这些步骤中有些是固定的,有些是可变的,可以使用模板方法模式。
  • 控制算法的流程: 当需要确保算法的某些步骤必须按照一定的顺序执行时,可以使用模板方法模式。

6 总结

模板方法模式通过将通用的算法步骤封装到抽象类中,允许子类重写或扩展特定的步骤,实现了算法的复用和扩展。它确保了算法的整体结构不被破坏,同时为子类提供了灵活性。在多个类具有相似的操作步骤时,模板方法模式是一种非常有效的设计模式。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 240909-ChuanhuChatGPT集成Ollama的环境配置
  • 101.游戏安全项目-创建人物对象结构
  • 游戏开发引擎___unity位置信息和unlit shader(无光照着色器)的使用,以桌子的渲染为例
  • 【devops】devops-git之介绍以及日常使用
  • 【代码随想录训练营第42期 Day57打卡 - 图论Part7 - Prim算法与Kruskal算法
  • oracle 使用 PL/SQL Developer创建表并插入单条、多条数据
  • MySQL——数据库的高级操作(二)用户管理(4)修改用户密码
  • 算法面经手撕系列(2)--手撕BatchNormlization
  • 基于鸿蒙API10的RTSP播放器(二:视频切换实现)
  • 类的继承性和多态性
  • 微生物分类检测系统源码分享
  • 004: VTK读入数据---vtkImageData详细说明
  • Go语言中的链表与双向链表实现
  • 食品分类2检测系统源码分享
  • 【Vue嵌套数据中,实现动态表头和内容】
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • leetcode388. Longest Absolute File Path
  • MYSQL 的 IF 函数
  • Node项目之评分系统(二)- 数据库设计
  • Redis字符串类型内部编码剖析
  • vue自定义指令实现v-tap插件
  • 老板让我十分钟上手nx-admin
  • 前端知识点整理(待续)
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 日剧·日综资源集合(建议收藏)
  • 算法---两个栈实现一个队列
  • 一些关于Rust在2019年的思考
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • # dbt source dbt source freshness命令详解
  • # 安徽锐锋科技IDMS系统简介
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (solr系列:一)使用tomcat部署solr服务
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (三)SvelteKit教程:layout 文件
  • .md即markdown文件的基本常用编写语法
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .net 调用php,php 调用.net com组件 --
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET轻量级ORM组件Dapper葵花宝典
  • .NET文档生成工具ADB使用图文教程
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • ?php echo ?,?php echo Hello world!;?
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [ACP云计算]易混淆知识点(考题总结)
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [BSidesCF 2019]Kookie1
  • [c]统计数字
  • [C++]命名空间等——喵喵要吃C嘎嘎
  • [Day 8] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • [Doc][px4][ros2][gazebo][yolov8]PX4-ROS2-Gazebo-YOLOv8
  • [Docker]六.Docker自动部署nodejs以及golang项目
  • [flutter]一键将YAPI生成的api.json文件转为需要的Dart Model类的脚本
  • [hdu2196]Computer树的直径