设计模式:模板模式(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方法将动态数据与模板文件进行替换,并将最终的输出发送给客户端。

《完结》

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

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

相关文章

C++初阶(五)类和对象

文章目录 一、C两大类型二、类的6个默认成员函数三、构造函数1、概念2、特性1、构造函数自动调用特性演示2、无参有参调用两种情况演示3、函数重载演示4、默认构造函数组成及演示5、内置类型成员不初始化的补丁演示 3、析构函数1、概念2、特性1、代码演示2、析构两种情况 4、构…

vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法

vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法 先看一下效果图&#xff08;想在表单里动态的增删 form-item&#xff0c;然后添加rules&#xff0c;校验其必填项&#xff1b; &#xff09;: html部分 <div v-for"(item, index) in …

GitHub下载太慢的解决方案

修改hosts文件&#xff1a; windows的hosts文件在 C:\Windows\System32\drivers\etc\hosts cmd管理员运行命令notepad C:\Windows\System32\drivers\etc\hosts 然后cmd命令重启网络ipconfig /flushdns windows修改hosts Ubuntu22.04修改hosts sudo vim /etc/hosts # This fil…

基于北方苍鹰优化的BP神经网络(分类应用) - 附代码

基于北方苍鹰优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于北方苍鹰优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.北方苍鹰优化BP神经网络3.1 BP神经网络参数设置3.2 北方苍鹰算法应用 4.测试结果…

13 Multi-Head Self-Attention(从空间角度解释为什么做多头)

博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https://github.com/nickchen121/Pre-training-language-model 配套博客链接:https://www.cnblogs.com/nickchen121/p/15105048.html 上节课回顾 0:40 At…

系统架构之微服务架构

微服务架构 一.传统的单体架构与微服务架构的区别1.1 单体架构1.1.1 优点1.1.2 缺点 1.2 微服务架构1.2.1 优点1.2.2 面临的问题与挑战 二. 微服务架构模式方案2.1 聚合器微服务2.2 链式微服务2.3 数据共享微服务2.4 异步消息传递微服务 三. SOA与微服务的区别 微服务&#xff…

JAVA毕业设计100—基于Java+Springboot+Vue的WMS仓库管理系统+移动端微信小程序(源码+数据库+部署视频)

基于JavaSpringbootVue的WMS仓库管理系统移动端(源码数据库部署视频) 一、系统介绍 本系统前后端分离带小程序 本系统分为管理员、用户角色(角色权限可自行分配) 功能列表&#xff1a; 1、 数据管理&#xff1a;物料数据管理、物料Bom管理、物料组管理、物料分类管理、供应…

uni-app:实现当前时间的获取,并且根据当前时间判断所在时间段为早上,下午还是晚上

效果图 核心代码 获取当前时间 toString()方法将数字转换为字符串 padStart(2, 0)&#xff1a;padStart()方法用于在字符串头部填充指定的字符&#xff0c;使其达到指定的长度。该方法接受两个参数&#xff1a;第一个参数为期望得到的字符串长度&#xff0c;第二个参数为要填充…

Java - 多进程编程(对比线程、API 操作)

目录 一、多进程编程 1.1、为什么要使用多进程编程 1.2、Java 中多进程编程的实现 1.2.1、前言 1.2.2、进程创建 1.2.3、进程等待 1.2.4、封装操作到一个工具类中 一、多进程编程 1.1、为什么要使用多进程编程 一个 .exe 文件执行以后&#xff0c;就会变成一个进程. 多…

vscode使用CSScomb插件

1. 安装 在设置中搜索csscomb&#xff0c;把Csscomb: Format On Save勾上 然后去edit in settings.json配置 2.使用 2.1 用官网提供的三种方法 https://github.com/csscomb/csscomb.js/tree/master/config 2.2 自定义 CSS 书写顺序规则可以参考这个荐腾讯 AollyTeam 团队的…

Java SSL/TLS证书认证逻辑

前言 最近做项目使用httpclient转发https请求&#xff0c;但是遇到一些坑&#xff0c;尤其是证书的认证&#xff0c;证书认证一般都是单向的&#xff0c;除非相互访问&#xff0c;证书一般基于host&#xff0c;但是如果访问需要ip&#xff0c;那么JDK默认的认证就会不通过&…

emqx 启动正常,但是1883端口无法telnet,emqx无法正常工作

emqx一直正常工作&#xff0c;后面突然就不工作了&#xff0c;查找日志&#xff0c;发现报错说设备空间不足&#xff0c;但是我记得华为云SSD从40G扩容到500G&#xff0c;不至于空间不足&#xff0c;于是运行df -Dh确实显示只有40G&#xff0c;运行lsblk确实有500G&#xff0c;…

基于Arrow的轻量线程池

基于Arrow的轻量线程池 大家好&#xff0c;我是光城&#xff0c;最近花了几周业余时间&#xff0c;开发出这款轻量线程池&#xff0c;代码也全部开源啦&#xff0c;欢迎大家star。 本线程池的设计与实现会有涉及非常多的知识&#xff0c;这些内容也都会以视频的方式分享在知识星…

每个epoch的溯源(MNE)

每个epoch的溯源&#xff1a; from mne.minimum_norm import apply_inverse_epochs stcs apply_inverse_epochs(epochs,inverse_operator,lambda2,method,pick_ori"normal"# naveevoked.nave, )

从零开始构建基于YOLOv5的目标检测系统

本博文从零开始搭建基于YOLOv5模型的目标检测系统&#xff08;具体系统参考本博主的其他博客&#xff09;&#xff0c;手把手保姆级完成环境的搭建。 &#xff08;1&#xff09;首先Windows R输入cmd命令后打开命令窗口&#xff0c;进入项目目录&#xff0c;本博文以野生动物…

交换机控制在同一个网段内的终端,用hybrid接口实现不同的IP通和不通。

实验效果&#xff1a;pc1和pc2不能通&#xff0c;但pc1和pc2分别可以和pc3通。 通过这个实验可以彻底掌握数据包在交换机上的进去的类型状态。 sw1配置&#xff1a; [sw1]dis current-configuration sysname sw1 vlan batch 10 20 100 interface GigabitEthernet0/0/1 port h…

计算机服务器中了勒索病毒怎么解决,勒索病毒解密流程,数据恢复

计算机服务器中了勒索病毒是一件非常令人头疼的事情&#xff0c;勒索病毒不仅会加密企业服务器中的数据&#xff0c;还会对企业计算机系统带来损害&#xff0c;严重地影响了企业的正常运转。最近&#xff0c;云天数据恢复中心工程师总结了&#xff0c;今年以来网络上流行的勒索…

Vue3中使用富文本编辑器

在vue3中我们可以使用wangeditor/editor、wangeditor/editor-for-vue来实现其功能 npm地址&#xff1a;https://www.npmjs.com/package/wangeditor/editor-for-vue/v/5.1.12?activeTabreadme 官网&#xff1a;Editor 1. 安装 pnpm add wangeditor/editor # 或者 npm inst…

卷积神经网络CNN学习笔记-卷积计算Conv2D函数的理解

目录 1.全连接层存在的问题2.卷积运算3.填充(padding)3.1填充(padding)的意义 4.步幅(stride)5.三维数据的卷积运算6.结合方块思考7.批处理8.Conv2D函数解析9.conv2d代码9.1 stride19.2 stride2 参考文章 1.全连接层存在的问题 在全连接层中&#xff0c;相邻层的神经元全部连接…