设计模式:模板模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
简介:
模板模式,它是一种行为型设计模式,它定义了一个操作中的算法的框架,将一些步骤延迟到子类中实现,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
通俗地说,模板模式就是将某一行为制定一个框架,然后子类填充细节。比如说做菜,流程通常就是洗菜、切菜、炒菜等步骤,那么这个流程就可以看作是一个模板,而具体做什么菜由子类来实现。
模板模式的使用场景:
1、一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。这种情况下,可以将一些通用的算法逻辑放在一个抽象类中,然后通过子类来提供具体的实现。
2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。这种情况下,可以将一些共同的行为放在一个父类中,然后通过继承和多态来实现相似的功能,避免在多个子类中重复编写相同的代码。
例如,在网络销售商品中,模板流程大体为:上架商品-下订单-发快递-收货,如果需要退货还需进行退货流程。这种情况下,可以将发快递和退货等公共流程提取出来放到一个父类中,然后通过子类来实现具体的流程。
模板模式的创建步骤如下:
1、定义抽象类:定义一个抽象类,将要执行的操作封装在方法中。这些方法应该是一个模板方法,包含一些基本的操作步骤。
2、定义模板方法:在抽象类中定义一个模板方法,该方法指定了算法的骨架,并调用其他方法实现具体的操作步骤。模板方法通常是一些基本的流程控制结构,如循环、条件语句等。
3、实现抽象方法:在抽象类中定义一些抽象方法,这些方法将在子类中被实现。这些方法通常是一些具体的操作步骤,如数据处理、界面渲染等。
4、创建子类:创建具体的子类,并实现抽象类中的抽象方法。这些方法将根据实际需求进行定制。
5、实例化对象:在客户端代码中实例化一个对象,并调用模板方法开始执行算法。
这些步骤是模板方法模式的核心。在实际应用中,可以根据具体的需求进行修改和扩展。例如,可以添加更多的抽象方法来细化算法的步骤,或者使用不同的继承结构来组织代码。
模板模式的优点,主要包括:
1、封装不变部分:通过将不变的行为放在父类中,可以减少子类的重复代码,并将这些不变的行为在多个子类中复用。
2、提取公共代码:模板模式可以在多个子类中复用公共代码,使得代码更加简洁、易于维护和修改。
3、行为由父类控制,子类实现:模板模式使得行为的变化更加容易适应,因为行为的变化可以在父类中定义和控制,而子类只需要实现具体的行为即可。
4、提高可复用性:模板模式使得算法的框架可以在多个应用中使用,提高了代码的可复用性。
5、提高可维护性:模板模式使得代码的结构更加清晰,易于维护和理解。
模板模式的缺点,主要包括:
1、类的数量增加:为了实现模板方法,需要在父类中定义一个抽象方法,并且每个子类都需要实现该方法,这样就导致类的数量增加,从而增加了系统的复杂度。
2、继承的固有缺点:如果父类添加了新的抽象方法,所有子类都需要增加该方法,这就增加了代码的维护难度。另外,如果一个子类需要同时实现其他接口或继承其他类,就需要编写更多的代码。
3、实现难度增加:模板方法模式需要开发者自行设计算法框架和流程控制,如果算法较为复杂,实现难度就会增加。
4、不够灵活:模板方法模式相对固定,不够灵活,不能够很好地适应变化。如果需要修改算法框架,就需要修改所有子类的实现,工作量较大。

示例:
一、C#模板模式
在C#中,我们可以使用抽象类或接口来实现模板模式。以下是一个使用抽象类的示例:
public abstract class AbstractTemplate
{ public void TemplateMethod() { Console.WriteLine("Subclass must implement steps"); } public abstract void SpecificStep();
} public class ConcreteTemplate : AbstractTemplate
{ public override void SpecificStep() { Console.WriteLine("This is a specific step"); }
}
//可以这样使用模板模式:
public static void Main(string[] args)
{ AbstractTemplate template = new ConcreteTemplate(); template.TemplateMethod(); // This will call SpecificStep and print "This is a specific step"
}
二、java模板模式
模板模式通常通过以下方式实现:
public abstract class AbstractTemplate { public void templateMethod() { System.out.println("AbstractTemplate says:"); doSomething(); doSomethingElse(); } public abstract void doSomething(); public abstract void doSomethingElse();
} public class ConcreteTemplate extends AbstractTemplate { public void doSomething() { System.out.println("ConcreteTemplate says:"); // specific behavior } public void doSomethingElse() { System.out.println("ConcreteTemplate says:"); // specific behavior }
}
public class Client{public static void Main(String[] args){AbstractTemplate template = new ConcreteTemplate();template.templateMethod(); }
}
三、javascript模板模式
在JavaScript中,模板模式的实现方式如下:
function Person(name, age) { this.name = name; this.age = age;
} Person.prototype.sayHello = function() { return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
}; const person1 = new Person("Alice", 25);
const person2 = new Person("Bob", 30); console.log(person1.sayHello()); // 输出:Hello, my name is Alice and I am 25 years old.
console.log(person2.sayHello()); // 输出:Hello, my name is Bob and I am 30 years old.
四、C++模板模式
C++模板可以分为函数模板和类模板。函数模板定义了一个通用的函数框架,可以接受不同的参数类型,并生成相应的函数实现。类模板则定义了一个通用的类,可以接受不同的数据类型作为成员变量类型,并生成相应的类实现。
下面是一个使用C++函数模板的示例:
template <typename T>
T add(T a, T b) { return a + b;
} int main() { int sum = add<int>(1, 2); // 使用整数类型参数 double avg = add<double>(1.0, 2.0); // 使用浮点数类型参数 return 0;
}
在上面的示例中,函数模板 add 可以接受任意类型的参数 a 和 b,并返回它们的和。在 main 函数中,我们使用整数类型和浮点数类型分别调用 add 函数,生成相应的代码实现。
除了函数模板,C++还支持类模板。类模板可以定义一个通用的类,可以接受不同的数据类型作为成员变量类型,并生成相应的类实现。下面是一个使用C++类模板的示例:
template <typename T>
class Array {
public: Array(int size) : size_(size), data_(new T[size]) {} ~Array() { delete[] data_; } T& operator[](int index) { return data_[index]; }
private: int size_; T* data_;
}; int main() { Array<int> int_array(10); // 使用整数类型参数 Array<double> double_array(5); // 使用浮点数类型参数 return 0;
}
在上面的示例中,类模板 Array 可以接受任意类型的参数 T 作为成员变量类型,并生成相应的类实现。在 main 函数中,我们使用整数类型和浮点数类型分别创建 Array 类的对象,生成相应的代码实现。
五、python模板模式
在python中有两种方式实现模板模式。
1、使用装饰器来扩展函数的行为来实现。装饰器可以在不修改函数代码的情况下添加新的行为。下面是一个简单的例子:
def template_method(func): def wrapper(*args, **kwargs): print("Before the function is called.") result = func(*args, **kwargs) print("After the function is called.") return result return wrapper @template_method
def add(x, y): return x + y print(add(2, 3))
在这个例子中,template_method 是一个装饰器,它定义了一个框架,在调用函数之前和之后打印一些信息。add 函数被装饰器装饰,因此它继承了装饰器的行为。当我们调用 add 函数时,它将在调用之前和之后打印信息,并返回函数的结果。
2、使用抽象基类(ABC)和多态来实现。抽象基类定义了一个通用的接口,子类必须实现这个接口。多态允许使用不同的子类来扩展父类的行为。下面是一个使用抽象基类和多态的例子:
from abc import ABC, abstractmethod class Shape(ABC): def draw(self): pass class Circle(Shape): def draw(self): print("Drawing circle") class Rectangle(Shape): def draw(self): print("Drawing rectangle") def draw_shape(shape): shape.draw() if __name__ == "__main__": shapes = [Circle(), Rectangle()] for shape in shapes: draw_shape(shape)
在这个例子中,Shape 是一个抽象基类,它定义了一个 draw 方法,子类必须实现这个方法。Circle 和 Rectangle 是 Shape 的子类,它们分别实现了 draw 方法。draw_shape 函数是一个模板方法,它接受一个 Shape 对象作为参数,并调用其 draw 方法。在主程序中,我们创建了一个包含不同形状的列表,并使用 draw_shape 函数来绘制它们。由于它们都继承自 Shape 类,因此它们都可以被 draw_shape 函数接受并正确绘制。
六、go模板模式
在Go语言中,没有直接称为"模板模式"的设计模式,但是有一种类似的行为可以通过使用函数和闭包来实现。
在Go语言中,可以通过定义一个父类和一个子类来实现类似模板方法模式的行为。父类可以包含一个或多个函数,这些函数可以调用子类的方法来实现算法的某些步骤。子类可以继承父类的函数,并重写其中的一些方法来改变算法的行为。
下面是一个简单的示例代码,实现类似模板方法模式的行为:
package main import "fmt" type Parent struct{} func (p *Parent) Algorithm() { fmt.Println("Parent's Algorithm") p.Step1() p.Step2()
} func (p *Parent) Step1() { fmt.Println("Parent's Step 1")
} func (p *Parent) Step2() { fmt.Println("Parent's Step 2")
} type Child struct { Parent
} func (c *Child) Step1() { fmt.Println("Child's Step 1")
} func main() { child := &Child{} child.Algorithm() // Output: Parent's Algorithm, Child's Step 1, Parent's Step 2
}
七、PHP模板模式
在PHP中,模板模式通常使用模板引擎来实现。
模板引擎是一种独立的中间件,用于处理模板和生成最终的输出。它负责解析模板文件,将动态数据与模板文件中的占位符进行替换,并将最终的输出发送给客户端。PHP中有很多流行的模板引擎,如Smarty、Twig和Blade等。
下面是一个简单的示例,演示了如何使用PHP模板模式:
//创建模板文件(template.php):
<html>
<head> <title>{{ title }}</title>
</head>
<body> <h1>{{ message }}</h1>
</body>
</html>
//创建PHP脚本(script.php):
<?php
// 加载并配置模板引擎(以Twig为例)
require_once 'vendor/autoload.php'; // 根据实际情况加载Composer依赖项
$loader = new \Twig\Loader\FilesystemLoader('path/to/templates');
$twig = new \Twig\Environment($loader); // 准备动态数据
$data = [ 'title' => 'Welcome', 'message' => 'Hello, world!'
]; // 渲染模板并输出结果
echo $twig->render('template.php', $data);
在上面的示例中,我们使用了Twig模板引擎来解析和渲染模板文件。在script.php中,我们首先加载并配置了Twig引擎,然后准备了一个包含动态数据的数组。最后,我们使用Twig的render方法将动态数据与模板文件进行替换,并将最终的输出发送给客户端。
《完结》
相关文章:
设计模式:模板模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
简介: 模板模式,它是一种行为型设计模式,它定义了一个操作中的算法的框架,将一些步骤延迟到子类中实现,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 通俗地说,模板模式就是将某一行…...
基于Java的图书商城管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...
PHP 基础
PHP 基础 概述 在PHP 文件中,可以与HTML 和JavaScript 混编。 开始标记<?php 表示进入PHP 模式,结束标记?>,标识退出PHP 模式。 PHP 模式之外的内容会被作为字符输出到浏览器中。 PHP 在服务端执行,HTML 和 JS 在浏览…...
Java RestTemplate使用TLS1.0(关闭SSL验证)
1. 问题 使用RestTemplate调用Http API时,服务器是TLS1.0,但是客户端Java默认禁止TLS1.0,会报错:org.springframework.web.client.ResourceAccessException: I/O error on POST request for “https://10.255.200.114/health”: …...
【进阶C语言】C语言文件操作
1. 为什么使用文件 2. 什么是文件 3. 文件的打开和关闭 4. 文件的顺序读写 5. 文件的随机读写 6. 文本文件和二进制文件 7. 文件读取结束的判定 8. 文件缓冲区 一、文件与文件的意义 1.文件的意义 文件的意义,无非就是为什么要使用文件? (1&…...
Django实现音乐网站 (21)
使用Python Django框架做一个音乐网站, 本篇音乐播放器功能完善及原有功能修改。 目录 播放列表修改 视图修改 删除、清空播放器 设置路由 视图处理 修改加载播放器脚本 模板修改 脚本设置 清空功能实现 删除列表音乐 播放列表无数据处理 视图修改 播放…...
LeetCode 面试题 10.11. 峰与谷
文章目录 一、题目二、C# 题解 一、题目 在一个整数数组中,“峰”是大于或等于相邻整数的元素,相应地,“谷”是小于或等于相邻整数的元素。例如,在数组{5, 8, 4, 2, 3, 4, 6}中,{8, 6}是峰, {5, 2}是谷。现…...
【专题】测试人员为什么需要学会做业务总结?
背景 如何回答以下这个问题的知识支撑:系统的测试重点在哪,难点是什么,怎么攻克,为什么要这样设计?项目交接效率? 同样是做业务测试,为什么有的人是A有的人只能C 二、框架 2.1 测试场景 重点…...
uni-app:实现当前时间的获取,并且根据当前时间判断所在时间段为早上,下午还是晚上
效果图 核心代码 获取当前时间 toString()方法将数字转换为字符串 padStart(2, 0):padStart()方法用于在字符串头部填充指定的字符,使其达到指定的长度。该方法接受两个参数:第一个参数为期望得到的字符串长度,第二个参数为要填充…...
C# .Net6 指定WSDL, 生成Webservice,调用该接口服务
C# .Net6 指定WSDL, 调用该接口服务。 IDE: Microsoft Visual Studio Community 2022 (64 位)平台:.Net6协议:Soap协议 Xml格式 功能 需要开发一个前置机程序, 用于和硬件程序交互,已知条件是:嵌入式同事…...
JS基本小知识:函数
目录 函数的基本概念 函数的定义和调用 函数的定义 函数的调用 函数的参数和返回值 参数的作用域和生命周期 返回值的作用和使用场景 匿名函数和箭头函数 匿名函数 本文将介绍 JavaScript 中的一个知识点:函数。函数是 JavaScript 中非常重要的一个概念&am…...
在Windows下Edge浏览器OA发起流程问题
在Edge浏览器中发起流程 如上图所示,不能正常打开Excel,自动将Excel表格转为了PDF 怎么处理?还得使用IE浏览器来访问,但打开IE后又自动跳转到Edge,根本就不给使用,在Edge下使用IE模式也解决不了这个问题。…...
2020年亚太杯APMCM数学建模大赛A题激光标记舱口轮廓生成求解全过程文档及程序
2020年亚太杯APMCM数学建模大赛 A题 激光标记舱口轮廓生成 原题再现: 激光是20中的一项重要发明世纪,它被称为“最锋利的刀”、“最精确的尺子”和“最不寻常的光”。 激光已越来越多地应用于工业加工, 其中可以是就业在各种加工业务例如作…...
【单元测试】--工具与环境
一、单元测试工具概览 1.1 JUnit JUnit 是一个广泛用于 Java 程序开发的开源测试框架。它是单元测试的标准工具之一,用于编写和运行测试用例,以确保 Java 程序的各个组件按预期工作。以下是一些关键特点和概念,来介绍 JUnit: 注…...
基于Java的汽车维修预约管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...
vscode调试container(进行rocksdb调试)+vscode比较git项目不同分支和fork的哪个分支
vscode调试container(进行rocksdb调试) 参考链接: https://blog.csdn.net/qq_29809823/article/details/128445308#t5 https://blog.csdn.net/qq_29809823/article/details/121978762#t7 使用vscode中的插件dev containners->点击左侧的…...
[python-大语言模型]从浅到深一系列学习笔记记录
整体学习路径参照:点这里 python-机器学习-深度学习-大语言模型-数据开发 面向开发者的LLM入门提示原则 面向开发者的LLM入门 学习链接: github地址:https://github.com/datawhalechina/prompt-engineering-for-developers 在线阅读地址&…...
Android 指定有线网或Wifi进行网络请求
Android 指定有线网或Wifi进行网络请求 文章目录 Android 指定有线网或Wifi进行网络请求一、前言:二、指定网络通讯测试1、 窗口命令 ping -I 网络节点 IP2、Java 代码指定特定网络通讯 三、指定特定网络的demo app 开发1、效果图:2、实际测试结果说明&a…...
消除过期的对象引用
Java虽然有自己的垃圾回收机制,但是并没有那么的智能,对于被引用的对象,就算我们已经不在使用它了,但是Java的回收机制是不会回收它们的,人们称之为“内存泄漏”。 以下为三种不同的内存泄漏场景,极其优化方案 1、只要类自己管理内存,就该警惕内存泄漏问题 例如Stack…...
【Shell】环境变量 自定义变量 特殊变量
Shell变量:环境变量 目标 1、理解什么是系统环境变量? 2、掌握常用的系统环境变量都有哪些? Shell变量的介绍 变量用于存储管理临时的数据, 这些数据都是在运行内存中的. 变量类型 系统环境变量 自定义变量 特殊符号变量 系统环境变…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
