设计模式-行为型模式-模板方法模式

news2024/9/25 15:24:50

一、什么是模板模式

        模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法骨架,允许子类在不改变算法整体结构的情况下重新定义算法的某些步骤。

        主要组成部分:

        1、模板方法(Template Method): 定义了算法的骨架结构,包含了一个算法的整体流程,并将某些步骤的实现推迟到子类中。通常作为一个抽象方法或者具有默认实现的方法。

        2、具体方法(Concrete Methods): 模板方法中的步骤可能有一些默认实现,在模板方法中直接实现的步骤。

        3、抽象方法(Abstract Methods): 在模板方法中留给子类实现的方法,用于子类实现具体步骤。

        工作原理:

        模板方法模式定义了一个固定算法的框架,其中一些步骤是固定的,而另一些可以由子类实现。抽象类中的模板方法规定了算法的结构和执行顺序,而具体的步骤则由子类实现。

二、场景模拟

        这里拿2023年海康威视秋招的一个问答题为例。题目是这么描述的:实现两个巡检任务,其中A巡检任务使用现场扫描二维码的方式巡检机房的服务器状态(正常/异常),B巡检任务使用远程视频方式巡检服务器正常运行率(百分比数字),两个巡检任务结束后都要提交巡检结果。使用模板方法设计模式解决。

        我们简单的将A和B任务的流程画出了,很简单,就是A使用二维码方式巡检,返回正常/异常的结果;B使用远程视频方式巡检,返回百分率。这里,我们发现,他们有着共同的流程,先巡检,再上报,可能有些方法的具体实现不一样,但是整体流程是确定的。

三、业务实现

        其中抽象类Inspect定义了巡检的流程,然后提供了默认的实现方法 。两个不同的巡检方法继承Inspect,可以根据需求自定义方法,也可以使用Inspect提供的默认实现方法。

3.1、使用模板类定义一个巡检框架

@Slf4j
public abstract class Inspect<T> {

    // 巡检名称
    private final String inspectName;

    public Inspect(String inspectName) {
        this.inspectName = inspectName;
    }

    public T startInspect(){
        initInspect();
        inspectFunction();
        return submitInspect();
    }

    /**
     * 初始化巡检方法
     */
    protected void initInspect(){
        log.info("初始化巡查系统" + inspectName);
    }

    // 模拟不同的巡检方式
    protected abstract void inspectFunction();

    // 返回巡检信息
    protected abstract T submitInspect();
}

可以看到上方定义了三个流程,首先初始化,然后模拟不同的巡检方式,最后返回巡检信息。流程是固定的,只不过不同的巡检可能使用不同的方式,所以需要写单独的类去实现。

3.2、子类继承模板抽象类后自定义

例如巡检A,使用的是二维码的形式巡检,并返回(正常/异常)状态,我们用布尔值模拟。

@Slf4j
public class AInspect extends Inspect<Boolean> {

    public AInspect(String inspectName) {
        super(inspectName);
    }

    @Override
    protected void inspectFunction() {
        log.info("使用二维码方式巡检……");
    }

    @Override
    protected Boolean submitInspect() {
        return true;
    }
}

巡检B,使用的是远程视频监控的形式,并返回百分比比例,我们用double模拟;

@Slf4j
public class BInspect extends Inspect<Double> {

    public BInspect(String inspectName) {
        super(inspectName);
    }

    @Override
    protected void inspectFunction() {
        log.info("使用远程视频监控方式巡检……");
    }

    @Override
    protected Double submitInspect() {
        return 88.88d;
    }
}

3.3、测试

public static void main(String[] args) {

        Inspect<Boolean> inspectA = new AInspect("A任务");
        Boolean resultA = inspectA.startInspect();
        log.info("A巡视结果:{}", resultA);

        Inspect<Double> inspectB = new BInspect("B任务");
        Double resultB = inspectB.startInspect();
        log.info("B巡视结果:{}", resultB);

    }

可以看到运行结果,巡检系统A和B分别用不同的方式完成了巡检,且流程一致。

四、小结

        模板方法定义了一个算法的骨架,将一些步骤推迟到子类去实现。如果在我们的项目中,有一个业务流程是固定的,但是实现业务的方式是多变的,我们可以考虑模板方法,来优化我们的代码结构。

        可能有些人分不清楚模板方法和策略模式的区别,这里我区分一下。

        首先就定义和结构方面:模板方法用抽象类定义了一系列的流程,子类继承他的流程,但是可以修改流程某个点的实现方式或者是继承父类的默认实现方式;策略模式是定义一个接口,多个类去实现这个接口,允许客户端在运行时选择使用的策略。

        它们的目的也是不一样的:模板方式是确保各个步骤执行顺序,一定层面上减少重复代码;策略模式是让调用者自由的选择实现方式或行为,且多个实现方式之前可以替换。

        区分谁是谁并不怎么重要,因为在一念之间,他们有可能会相互替换,需要看自己的业务需求。而且很多时候,这两种设计模式可能配合使用,实现拓展和定制,这里我举例一种情况。就拿策略模式这个来说,我这里只写了计算某种材料的计算策略,但是在实际的业务中,我们可能需要统计这一个月或者一年的材料成本量,就简单来说,我们需要算出这一个月的使用量,然后这一年的使用量是这12个月加起来的使用量。这个流程就大致为:计算出某一条记录的成本;计算出一个月的成本;计算出一年的成本。我们就可以定义一个模板方法,算不同材料的年成本。这里我们就可以嵌套进去我们的策略模式,让两者搭配使用,完成业务需求。当然两者配合的场景可能有很多,这里我举得例子可能不是那么恰当,但是也差不多这个意思。

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

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

相关文章

如何在CSDN植入广告

如何在CSDN植入广告 概述 如果你的博客访问量很大&#xff0c;你可以通过如下方式在博客上放置广告而通过博客赚钱 广告联盟 google adsense 链接&#xff1a;Adsense 比较主流的应该是Google Adsense&#xff0c;可以配置自动广告&#xff08;包含 业内广告、锚定广告、侧…

kafka 磁盘扩容与数据均衡实在操作讲解

文章目录 一、概述1&#xff09;Kafka 磁盘扩容概述2&#xff09;Kafka 数据均衡概述 二、K8s 集群部署三、kafka on k8s 环境部署1&#xff09;安装 helm2&#xff09;安装 zookeeper1、添加源并下载部署包2、修改配置3、开始安装 zookeeper4、测试验证5、卸载 3&#xff09;安…

Linux线程编程

Linux线程编程初步 一些历史背景 Linux间接起源于Unix&#xff0c;而Linux诞生时并不存在 "线程"的概念。在20世纪90年代线程才流行起来&#xff0c;POSIX Thread标准于 1995年确立。Unix中引入 Thread 之后&#xff0c;大量函数被重写&#xff0c;信号机制也变得复…

通过汇编理解cortex-m3:第0章

第0章&#xff1a;准备工作 基本想法&#xff1a;利用汇编和gdb调试&#xff0c;来学习cortex-m3汇编指令&#xff0c;以及一些寄存器的功能。 软件和硬件&#xff1a; 硬件&#xff1a;韦东山瑞士军刀中的最小核心板&#xff08;STM32F103C8T6&#xff09; STLINK-V2&#…

B-2:Linux系统渗透提权

B-2:Linux系统渗透提权 服务器场景:Server2204(关闭链接) 用户名:hacker 密码:123456 1.使用渗透机对服务器信息收集,并将服务器中SSH服务端口号作为flag提交; 使用nmap扫描,发现ssh服务端口为2283 Flag:2283 2.使用渗透机对服务器信息收集,并将服务器中…

算法之路(二)

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 : 算法小能手 &#x1f606;今日分享 : 你知道北极熊的皮肤是什么颜色的吗&#xff1f;&#xff08;文章结尾有答案哦&#xff01;&#xff09; 文章目录 力扣的209题✔解题思路✔代码:✔总结: 力扣的3题✔解题思路&#xff1a…

变频器干扰PLC,我们是这么解决的……

PLC是变频器的上位机&#xff0c;但是&#xff0c;在很多工程现场中&#xff0c;经常也会出现这样的问题&#xff0c;就是变频器开始运行后&#xff0c;PLC就开始罢工了&#xff0c;有的时候死机&#xff0c;有的时候指令传达不畅&#xff0c;有的时候会出现通讯时断时续等等&a…

【【VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 】】

VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 LCD 的构造是在两片平行的玻璃基板当中放置液晶盒&#xff0c;下基板玻璃上设置 TFT&#xff08;薄膜晶体管&#xff09;&#xff0c;上基板玻璃上设置彩色滤光片&#xff0c;通…

Asp.net MVC Api项目搭建

整个解决方案按照分层思想来划分不同功能模块&#xff0c;以提供User服务的Api为需求&#xff0c;各个层次的具体实现如下所示&#xff1a; 1、新建数据库User表 数据库使用SQLExpress版本&#xff0c;表的定义如下所示&#xff1a; CREATE TABLE [dbo].[User] ([Id] …

MISRA 2012学习笔记(5)-Rules 8.10

文章目录 Rules8.10 基本类型模型(The essential type model)8.10.1 原理8.10.2 基本类型(Essential type)Rule 10.1 操作数不得具有不适当的基本类型Rule 10.2 在加减法运算中&#xff0c;不得不当使用本质为字符类型的表达式Rule 10.3 表达式的值不得赋值给具有较窄基本类型或…

软考小记-软件工程

模块的控制范围包括模块本身及其所有的从属模块。模块的作用范围是指模块一个判定的作用范围&#xff0c;凡是受这个判定影响的所有模块都属于这个判定的作用范围.&#xff0c;原则上一个模块的作用范围应该在其控制范围之内&#xff0c;若没有&#xff0c;则可以将判定所在模块…

云课五分钟-0B快速排序C++示例代码-注释和编译指令

前篇&#xff1a; 云课五分钟-0ALinux文件系统及权限-查询命令如何使用 智能大模型个人感觉完全颠覆式改变了学习和教学的模式&#xff0c;知识的重要性荡然无存。 越来越需要重视思路和方法&#xff0c;创新和创意。 090A&#xff1a;接着如下 Linux基础入门的内容包括以…

Spring Cloud学习(十)【Elasticsearch搜索功能 分布式搜索引擎02】

文章目录 DSL查询文档DSL查询分类全文检索查询精准查询地理坐标查询组合查询相关性算分Function Score Query复合查询 Boolean Query 搜索结果处理排序分页高亮 RestClient查询文档快速入门match查询精确查询复合查询排序、分页、高亮 黑马旅游案例 DSL查询文档 DSL查询分类 …

Transformer中位置嵌入的几种形式对比

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

map与set的封装

目录 红黑树的结点 与 红黑树的迭代器 红黑树的实现&#xff1a; 迭代器&#xff1a; ​编辑 红黑树的查找&#xff1a; 红黑树的插入&#xff1a; ​编辑 检查红色结点&#xff1a;​编辑红黑树的左旋 ​编辑红黑树的右旋 ​编辑红黑树的双旋 Map的封装 ​编辑set的…

运行ps显示msvcp140.dll丢失怎么恢复?msvcp140.dll快速解决的4个不同方法

msvcp140.dll无法继续执行代码的主要原因有以下几点 系统缺失&#xff1a;msvcp140.dll是Visual Studio 2015编译的程序默认的库文件&#xff0c;如果系统中没有这个库文件&#xff0c;那么在运行相关程序时就会出现找不到msvcp140.dll的错误提示。 文件损坏&#xff1a;如果…

pythorch的numel()函数计算模型大小与现存占用

本文解释简单给一个模型列子记录如何计算该模型参数量与模型显存占用情况&#xff0c;该文直接调用torchvision库的模型文件构建模型model&#xff0c;在使用parameters()函数遍历&#xff0c;并在遍历情况下使用numel()函数记录模型参数量与显存占用。 代码如下&#xff1a; …

C/C++通过位操作实现2个uint32_t合并为uint64_t

#include <iostream> using namespace std;int main() {uint32_t a 10;uint32_t b 600;//先将uint32_t的a转为uint64_t&#xff0c;此时a前面32位都是0&#xff0c;然后左移32位&#xff0c;此时右32位为0&#xff0c;最后加上uint32_t类型的b&#xff0c;填充右32位的…

【心得】基于flask的SSTI个人笔记

目录 计算PIN码 例题1 SSTI的引用链 例题2 SSTI利用条件&#xff1a; 渲染字符串可控&#xff0c;也就说模板的内容可控 我们通过模板 语法 {{ xxx }}相当于变相的执行了服务器上的python代码 利用render_template_string函数参数可控&#xff0c;或者部分可控 render_…

LDO线性稳压器要不要并联二极管?

昨天介绍过了LDO是什么东西&#xff0c;那么对于它的应用场景是怎么的呢&#xff1f;LDO要不要并联二极管呢&#xff1f; 一般来说&#xff0c;LDO是不需要并联二极管的。 看下图第一个是典型电路&#xff0c;第二个是带可调节电压功能的LDO典型电路&#xff0c;从图里就可以…