模板方法模式——定义算法的框架

news2024/12/27 11:17:35

1、简介

1.1、概述

模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中。在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

模板方法模式是一种基于继承的代码复用基本技术。

1.2、定义

模板方法模式(Template Method Pattern):定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法模式是一种类行为型模式。

2、解析

2.1、UML类图

模板方法模式结构比较简单,其核心是抽象类和其中的模板方法的设计,其结构如下图所示:
在这里插入图片描述

  1. AbstractClass(抽象类):在抽象类中定义了一系列基本操作(Primitive Operations),这些基本操作可以是具体的,也可以是抽象的。每个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架。模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
  2. ConcreteClass(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。

2.2、模板方法和基本方法

在使用模板方法模式时,开发抽象类的软件设计师和开发具体子类的软件设计师之间可以进行协作。一个设计师负责给出一个算法的轮廓和框架,另一些设计师则负责给出这个算法的各个逻辑步骤。实现这些具体逻辑步骤的方法即为基本方法,而将这些基本方法汇总起来的方法即为模板方法,模板方法模式的名字也因此而来。

  1. 模板方法:一个模板方法是定义在抽象类中的、把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模板方法定义在抽象类中,并由子类不加以修改地完全继承下来(在Java语言中,可以将模板方法定义为final方法)。模板方法是一个具体方法,它给出了一个顶层逻辑框架,而逻辑的组成步骤在抽象类中可以是具体方法,也可以是抽象方法。由于模板方法是具体方法,因此模板方法模式中的抽象层只能是抽象类,而不是接口。
  2. 基本方法:基本方法是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为3种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。

(1)抽象方法:一个抽象方法由抽象类声明,由其具体子类实现。在Java语言里一个抽象方法以abstract关键字标识。
(2)具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
(3)钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。

在模板方法模式中,钩子方法有两类。第一类钩子方法可以与一些具体步骤“挂钩”,以实现在不同条件下执行模板方法中的不同步骤。这类钩子方法的返回类型通常是boolean类型,方法名一般为is×××(),用于对某个条件进行判断。如果条件满足则执行某一步骤,否则将不执行。代码片段如下:

// 模板方法
public void template(){
  open();
  display();
  if(isPrint()){
     print();
  }

  // 构子方法
  public boolean isPrint(){
     return true;
  }
}

在以上代码中,isPrint()方法即是钩子方法,它可以决定print()方法是否执行。一般情况下,钩子方法的返回值为true。如果不希望某方法执行,可以在其子类中覆盖钩子方法,将其返回值改为false即可。这种类型的钩子方法可以控制方法的执行,对一个算法进行约束。

还有一类钩子方法就是方法体为空的具体方法,子类可以根据需要覆盖或者继承这些钩子方法。与抽象方法相比,这类钩子方法的好处在于子类如果没有覆盖父类中定义的钩子方法,编译也可以正常通过,但是如果没有覆盖父类中声明的抽象方法,编译将报错。

模板方法模式中,抽象类的典型代码如下:

abstract class AbstractClass{
   // 模板方法
   
   // 基本方法——具体方法
   public void primitiveOperation1(){
      // 实现代码
   }
   
   // 基本方法——抽象方法
   public abstract void primitiveOperation2();
   
      // 基本方法——构子方法
   public abstract void primitiveOperation3(){
    
   }
}

在抽象类中,模板方法templateMethod()定义了算法的框架,在模板方法中调用基本方法以实现完整的算法。每一个基本方法如primitiveOperation1()、primitiveOperation2()等均实现了算法的一部分,对于所有子类都相同的基本方法可由父类提供具体实现,例如primitiveOperation1()。否则在父类中声明为抽象方法或钩子方法,由不同的子类提供不同的实现,例如primitiveOperation2()和primitiveOperation3()。

可在抽象类的子类中提供抽象步骤的实现,也可覆盖父类中已经实现的具体方法。具体子类的典型代码如下:

public ConcreteClass extends AbstractClass{
   public void primitiveOperation2(){
      // 实现代码
   }
   
      public void primitiveOperation3(){
      // 实现代码
   }
}

在模板方法模式中,由于面向对象的多态性,子类对象在运行时将覆盖父类对象,子类中定义的方法也将覆盖父类中定义的方法。因此程序在运行时,具体子类的基本方法将覆盖父类中定义的基本方法,子类的钩子方法也将覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。

3、模板方法模式总结

模板方法模式是一种基于继承的代码复用技术,它体现了面向对象的诸多重要思想,是一种使用频率较高的模式。模板方法模式广泛应用于框架设计(例如Spring、JUnit等)中,以确保通过父类来控制处理流程的逻辑顺序(例如框架的初始化、测试流程的设置等)。

3.1、主要优点

  1. 模板方法模式在父类中形式化地定义一个算法,而由它的子类来实现细节的处理。在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  2. 模板方法模式是一种代码复用技术,它在类库设计中尤为重要。它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为。它鼓励恰当使用继承来实现代码复用。
  3. 模板方法模式可实现一种反向控制结构。通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  4. 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。

3.2、主要缺点

模板方法模式的主要缺点是:需要为每一个基本方法的不同实现提供一个子类。如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象。此时,可结合桥接模式来进行设计。

3.3、适用场景

  1. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即一次性地实现一个算法的不变部分,并将可变的行为留给子类来实现。
  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
  3. 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

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

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

相关文章

js沙箱逃逸

目录 一、什么是沙箱(sandbox) 二、沙箱技术的实现 & node.js 2.1简单沙箱程序示例 2.2this.tostring S1: S2: 三、arguments.callee.caller 一、什么是沙箱(sandbox) 在计算机安全性方面,沙箱(沙盒、sanbox&#xff…

【【萌新的STM32学习-4】】

萌新的STM32学习-4 STM32系统框架 1.1 Cortex M 内核& 芯片 F1有四个驱动单元 四个被动单元 AHB 高级高性能总线 APB 高级外围总线 部分系统结构 最上面的ICode 总线直接连接到了内部Flash 不需要通过总线矩阵 . D Code 总线(D - Bus) 这是Cort…

Kubernetes高可用集群二进制部署(五)kubelet、kube-proxy、Calico、CoreDNS

Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署(二)ETCD集群部署 Kubernetes高可用集群二进制部署(三)部署…

Delphi Enterprise Crack

Delphi Enterprise Crack Delphi帮助您使用Object Pascal为Windows、Mac、Mobile、IoT和Linux构建和更新数据丰富、超连接、可视化的应用程序。Delphi Enterprise适合开发团队构建客户端/服务器或多层应用程序、REST服务等。 Delphi功能 单一代码库-用更少的编码工作为所有主要…

MySQL 详细学习教程【万字长文, 建议收藏】

目录 1. Mysql入门1.1 Mysql5.7 安装配置1.2 命令行连接到Mysql1.3 图形化软件1.3.1 Navicat1.3.2 SQLyog 1.4 数据库三层结构 2. Java操作数据库、表2.1 创建数据库2.2 查询数据库2.3 备份恢复数据库2.4 创建表2.5 修改表 3 CRUD3.1 insert插入3.2 update修改3.3 delete修改3.…

一篇文章搞定《LeakCanary源码详解(全)》

一篇文章搞定《LeakCanary源码解析》 前言LeakCanary和LeakCanary2区别LeakCanary的快速使用第一步:添加依赖第二步:初始化LeakCanary第三步:运行应用程序并监测内存泄漏 LeakCanary基础铺垫四大引用WeakReference和ReferenceQueueRefercence…

【Spring】(二)从零开始的 Spring 项目搭建与使用

文章目录 前言一、Spring 项目的创建1.1 创建 Maven 项目1.2 添加 Spring 框架支持1.3 添加启动类 二、储存 Bean 对象2.1 创建 Bean2.1 将 Bean 注册到 Spring 容器 三、获取并使用 Bean 对象3.1 获取Spring 上下文3.2 ApplicationContext 和 BeanFactory 的区别3.3 获取指定的…

2023-02-03——2023-08-03,半年以来与客服交流的记录【CSND 文章撰写 网站使用求解】客服咨询交流记录(长期更新ing)

这世界上久处不厌,都是因为用心。 🎯作者主页: 追光者♂🔥 🌸个人简介: 💖[1] 计算机专业硕士研究生💖 🌿[2] 2023年城市之星领跑者TOP1(哈尔滨)🌿 🌟[3] 2022年度博客之星人工智能领域TOP4🌟 🏅[4] 阿里云社区特邀专家博主🏅 🏆

Cesium 实战教程 - 调整 3dtiles 倾斜摄影大小

Cesium 实战教程 - 调整 3dtiles 倾斜摄影大小 核心代码完整代码在线示例 之前由于误解遇到一个特殊的需求:想要把三维球上叠加倾斜摄影进行自由放大缩小,跟随地图的缩放进行缩放。 后来经过搜索、尝试,终于实现了需求。 但是,后…

什么是强化学习?

📝什么是强化学习? 1. 📝监督,非监督,强化2. 📝非 i.i.d3. 📝强化学习基本形式4. 📝马尔可夫过程 🌟 强化学习(Reinforcement Learning,RL&#x…

windows安装kafka配置SASL-PLAIN安全认证

目录 1.Windows安装zookeeper: 1.1下载zookeeper 1.2 解压之后如图二 1.3创建日志文件 1.4复制 “zoo_sample.cfg” 文件 1.5更改 “zoo.cfg” 配置 1.6新建zk_server_jaas.conf 1.7修改zkEnv.cmd 1.8导入相关jar 1.9以上配置就配好啦,接下来启…

小红书博主排名丨狂揽近百万粉丝,女性议题成“爆款制造机”?

从上野千鹤子和北大女生的对谈,到电影《消失的她》,再到引爆“粉色狂潮”的电影《芭比》,近年来,女性话题、两性情感话题成为社会热门议题。“踩过恋爱所有坑,想给姑娘撑把伞”,近期,小红书博主…

2023年华数杯数学建模B题思路代码分析 - 不透明制品最优配色方案设计

# 1 赛题 B 题 不透明制品最优配色方案设计 日常生活中五彩缤纷的不透明有色制品是由着色剂染色而成。因此,不透明 制品的配色对其外观美观度和市场竞争力起着重要作用。然而,传统的人工配色 存在一定的局限性,如主观性强、效率低下等。因此…

docker容器学习笔记1

docker容器是干什么用的 docker就是一个轻量级的虚拟机,是一个容器,隔离性好,能够确保环境的统一,有效利用系统资源,轻松迁移和拓展。简单的可以理解为容器就是一个小型功能齐全的虚拟机。 实际上是如何使用的呢&…

RocketMQ发送消息超时异常

说明:在使用RocketMQ发送消息时,出现下面这个异常(org.springframework.messging.MessgingException:sendDefaultImpl call timeout……); 解决:修改RocketMQ中broke.conf配置,添加下…

2023华数杯数学建模竞赛C题思路解析

如下为:2023华数杯数学建模竞赛C题 母亲身心健康对婴儿成长的影响 的思路解析 C题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一,她不仅为婴儿提供营养物质和身体保护,还为婴儿提供情感支持和安全感。母亲心理健康状态的不…

HCIP作业3

题目 配置IP地址 R1 [r1]int g0/0/1 [r1-GigabitEthernet0/0/1]ip add 192.168.1.1 24 [r1-Serial4/0/0]ip add 12.1.1.1 24 R2 [r2]int s4/0/0 [r2-Serial4/0/0]ip add 12.1.1.2 24 [r2-Serial4/0/0]int s4/0/1 [r2-Serial4/0/1]ip add 32.1.1.1 24 [r2-Serial4/0/1]in…

数据管理基础知识

数据管理原则 数据管理与其他形式的资产管理的共同特征,涉及了解组织拥有哪些数据以及可以使用这些数据完成哪些工作,然后确定如何最好的使用数据资产来实现组织目标与其他流程一样,他必须平衡战略和运营需求,通过遵循一套原则&a…

k8s nginx+ingress 配置

1 nginx> ingress 配置: 2 nginx >service 配置 3 nginx pod配置: 4 nginx.conf 配置文件: # web端v1server{listen 30006;add_header Strict-Transport-Security "max-age31536000; includeSubDomains";#add_header Content…

【练】要求定义一个全局变量 char buf[] = “1234567“,创建两个线程,不考虑退出条件,打印buf

要求定义一个全局变量 char buf[] "1234567",创建两个线程,不考虑退出条件,另: A线程循环打印buf字符串,B线程循环倒置buf字符串,即buf中本来存储1234567,倒置后buf中存储7654321. 不…