设计模式:模板模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

news2025/5/25 23:28:10

简介:

模板模式,它是一种行为型设计模式,它定义了一个操作中的算法的框架,将一些步骤延迟到子类中实现,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
通俗地说,模板模式就是将某一行为制定一个框架,然后子类填充细节。比如说做菜,流程通常就是洗菜、切菜、炒菜等步骤,那么这个流程就可以看作是一个模板,而具体做什么菜由子类来实现。

模板模式的使用场景:
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.coloradmin.cn/o/1117105.html

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

相关文章

微信小程序数据交互------WXS的使用

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 1.数据库连接 数据表结构&#xff1a; 数据测式&#xff1a; 2.后台配置 pom.xml <?xml version&quo…

重磅发布!RflySim Cloud 智能算法云仿真平台亮相,助力大规模集群算法高效训练

RflySim Cloud智能算法云仿真平台&#xff08;以下简称RflySim Cloud平台&#xff09;是由卓翼智能及飞思实验室为无人平台集群算法验证、大规模博弈对抗仿真、人工智能模型训练等前沿研究领域研发的平台。主要由环境仿真模块、物理效应计算模块、多智能体仿真模块、分布式网络…

Python安装使用graphviz经验,Format: “png“ not recognized

Graphviz 是一款由 AT&T Research 和 Lucent Bell 实验室开源的可视化图形工具&#xff0c;可以很方便的用来绘制结构化的图形网络&#xff0c;支持多种格式输出。Graphviz 输入是一个用 dot 语言编写的绘图脚本&#xff0c;通过对输入脚本的解析&#xff0c;分析出其中的点…

摆闸机的应用领域和性能特点

摆闸机是一种常用于门禁控制和人员管理的设备&#xff0c;它具有以下应用领域和性能特点&#xff1a; 应用领域&#xff1a; 门禁控制&#xff1a;摆闸机可以用于各种场合的门禁控制&#xff0c;如小区、写字楼、学校、医院等。人员管理&#xff1a;摆闸机可以用于管理进出人…

最优化:建模、算法与理论(最优性理论2

5.7 约束优化最优性理论应用实例 5.7.1 仿射空间的投影问题 考虑优化问题 min ⁡ x ∈ R n 1 2 ∣ ∣ x − y ∣ ∣ 2 2 , s . t . A x b \min_{x{\in}R^n}\frac{1}{2}||x-y||_2^2,\\ s.t.{\quad}Axb x∈Rnmin​21​∣∣x−y∣∣22​,s.t.Axb 其中 A ∈ R m n , b ∈ R m …

【软考-中级】系统集成项目管理工程师-人力资源管理历年案例

持续更新。。。。。。。。。。。。。。。 目录 2019 下 试题三(20分)背诵整理1. 冲突管理的6种方法2. 获取项目人力资源的依据 系列文章 2019 下 试题三(20分) 阅读下列说明&#xff0c;回答问题 1至问题 3&#xff0c;将解答填入答题纸的对应栏内     某公司承接了一个软件…

Java BigDecimal计算及转换

BigDecimal应用汇总 1、负数转正数 a.abs(); 相当于&#xff1a;绝对值2、加法 a.add(b)3、减法 a.subtract(b) 相当于&#xff1a;a-b4、乘法 a.multiply(b)5、除法 a.divide(b) 相当于&#xff1a;a/b6、处理小数 BigDecimal.setScale()方法用于格式化小数点 setScale…

C++ vector 的使用

CSDN的uu们&#xff0c;大家好。这里是C入门的第十七讲。 座右铭&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;C专题 目录 1. 构造函数 1.1 vector(size_t n, const T& val T()) 1.2 vector…

laravel框架介绍(一) 开发环境配置

一.编译及开发工具 PHPStudy是一个windows下的Apache/NgnixPHPMySQL的集成开发环境 优点: 便于安装, 部署方便服务器版本快速切换集成了很多实用的工具 ​​​​​​小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; 二.配置和工具 2.1&#xff0c;Apache安装与…

论坛介绍|COSCon'23 开源百宝箱(T)

众多开源爱好者翘首期盼的开源盛会&#xff1a;第八届中国开源年会&#xff08;COSCon23&#xff09;将于 10月28-29日在四川成都市高新区菁蓉汇举办。本次大会的主题是&#xff1a;“开源&#xff1a;川流不息、山海相映”&#xff01;各位新老朋友们&#xff0c;欢迎到成都&a…

聊聊设计模式--简单工厂模式

简单工厂模式 ​ 前面也学了很多各种微服务架构的组件&#xff0c;包括后续的服务部署、代码管理、Docker等技术&#xff0c;那么作为后端人员&#xff0c;最重要的任务还是代码编写能力&#xff0c;如何让你的代码写的漂亮、易扩展&#xff0c;让别人一看赏心悦目&#xff0c…

PAM从入门到精通(十七)

接前一篇文章&#xff1a;PAM从入门到精通&#xff08;十六&#xff09; 本文参考&#xff1a; 《The Linux-PAM Application Developers Guide》 PAM 的应用开发和内部实现源码分析 先再来重温一下PAM系统架构&#xff1a; 更加形象的形式&#xff1a; 六、整体流程示例 2.…

【SpringBoot底层原理】SpringBoot底层原理实践(一)——手撕SpringBoot容器(幼儿园版)

Spring底层原理实践&#xff08;一&#xff09;——手撕Spring容器&#xff08;幼儿园版&#xff09; 0. 前言1. 依赖2. 注解3. Bean定义类4. 容器接口5. 配置类6. 测试Bean7. 启动类8. 容器实现类8.1 容器初始化8.2 获取Bean8.3 创建Bean 9. 测试 0. 前言 SpringBoot项目创建…

Character Animator 2024(Ch2024):打造生动角色,让动画设计更上一层楼

Character Animator 2024是一款专为角色动画设计师打造的软件&#xff0c;它可以帮助设计师快速创建出丰富多彩的角色动画。无论是初学者还是专业设计师&#xff0c;都可以通过Character Animator 2024轻松实现自己的创意。 Ch2024独特优势&#xff1a; 实时角色动画&#xf…

进程【Linux系统编程】

一、先谈硬件——冯诺依曼体系结构 存储器&#xff1a;内存&#xff08;硬盘是外存&#xff09; 输入设备&#xff1a;鼠标、键盘、摄像头、话筒、磁盘、网卡…… 输出设备&#xff1a;显示器、播放器硬件、磁盘、网卡…… 输入输出设备是外部设备&#xff0c;简称外设。 中央…

做一个最新版的淘宝客返利程序源码有多难?

我们都知道淘宝客返利程序成为了很多人的创业和赚钱的工具。这种程序允许通过推广淘宝商品来获得佣金。然而&#xff0c;你知道构建这样一个淘宝客返利程序有多难吗&#xff1f;今天我们就从最基本的API说起&#xff0c;现在我将介绍构建一个最新版淘宝客返利程序所需的关键API…

学习学不进去的时候怎么办?

01 人生很难只有欢声笑语,学习道路也一样。 有时候,我们会面临进退两难的情形: 明明知道应该学,却仿佛被定格在原地,一步也迈不出去。 这种状态为通常被称为“学不进去”&#xff0c;这时该怎么办? 其实, “学不进去”的原因可谓千头万绪,但归根结底,大抵可归为两类: 外在环境…

Python--练习:使用while循环求1..100的和

案例&#xff1a;使用while循环求1..100的和 思考&#xff1a; 先套用原有基础模式&#xff0c;之后再思考其他的。 while循环的基本语法&#xff1a; 对于循环次数已知的情况&#xff0c;建议使用while循环 因为是知道次数的&#xff0c;所以可以用一个计数器。程序里面&am…

【前端】图片裁剪路径绘制及图片不规则裁剪

说明 项目中可能需要用户根据展示的图片&#xff0c;然后绘制需要裁剪的路径&#xff0c;再根据绘制的坐标进行裁剪&#xff0c;以下是前端的裁剪路径绘制的代码示例&#xff0c;后端可以根据当前的获取到的坐标进行裁剪&#xff0c;裁剪的坐标保存在coordinate数组中。 代码 …