Java设计模式:模板方法模式

2023-12-18

❤ 作者主页: 欢迎来到我的技术博客 ????
❀ 个人介绍:大家好,本人热衷于 Java后端开发 ,欢迎来交流学习哦!( ̄▽ ̄)~*
???? 如果文章对您有帮助,记得 关注 点赞 收藏 评论 ⭐️⭐️⭐️
???? 您的支持将是我创作的动力,让我们一起加油进步吧!!!????????

一、模板方法模式的定义

在软件开发中,某个方法的实现需要多个步骤,其中有些步骤是固定的,而有些步骤并不固定,存在可变性。为了提高代码的复用性和系统的灵活性,可以使用 模板方法模式 的设计模式对这类情况进行设计。

在模板方法模式中将实现功能的每一步骤所对应的方法称为 基本方法 ,而将调用这些基本方法同时定义基本方法的执行次序的方法称为 模板方法

定义: 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

模板方法模式将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称为模板方法的方法的定义这些基本方法的执行次序,并且可以通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。


二、模板方法模式的结构

模板方法模式包含以下重要角色:

  • 抽象类 : 负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。

    • 模板方法 : 定义了算法的骨架,按某种顺序调用其包含的基本方法。

    • 基本方法 : 是实现算法中各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:

      • 抽象方法 : 一个抽象方法由抽象类声明、由其具体子类实现。
      • 具体方法 : 一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
      • 钩子方法 : 在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
        一般钩子方法是用于判断的逻辑方法,这类方法名一般为 isXxx ,返回值类型为 boolean 类型。
  • 具体子类 : 实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤。


三、模板方法模式的实现

需求案例:去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、离开银行等操作。

我们可以发现,在这个流程中取号、排队和对离开银行的操作对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。

现在使用模板方法模式来实现上述案例,类图如下:
在这里插入图片描述

具体的类设计如下:

抽象类:

public abstract class AbstractClass {

    //模板方法(定义基本方法的执行顺序)
    public final void service() {
        getNum();
        doWait();
        doService();
        doExit();
    }
		
	//下面的方法都称为基本方法
    //第一步:取号(一样的,所以直接实现)
    public void getNum() {
        System.out.println("取号");
    }

    //第二部:排队(一样的,所以直接实现)
    public void doWait() {
        System.out.println("排队");
    }

    //第三步:办理具体业务(不一样,由子类实现)
    public abstract void doService();

    //第四步:离开银行(一样的,所以直接实现)
    public void doExit() {
        System.out.println("离开银行");
    }

}

存款业务类:

public class SaveMoney extends AbstractClass {

    public void doService() {
        System.out.println("办理存款业务");
    }
}

取款业务类:

public class TakeMoney extends AbstractClass  {

    public void doService() {
        System.out.println("办理取款业务");
    }
}

客户端类:

public class client {

    public static void main(String[] args) {

        //办理存款业务
        SaveMoney saveMoney = new SaveMoney();
        saveMoney.service();

        System.out.println("---------------");

        //办理取款业务
        TakeMoney takeMoney = new TakeMoney();
        takeMoney.service();
    }

}

测试结果如下:
在这里插入图片描述

注意:为防止恶意操作,一般模板方法都加上 final 关键词。


四、模板方法模式的扩展

在上述的案例中,在现实生活中像取号和排队操作是不一定需要执行,比如一般在一般中如果是VIP的话那去办理业务一般是有独立的窗口,不需要去取号和排队的,因此,VIP的用户只需执行办理具体业务和离开银行即可。

我们可以引入模板方法模式中的 钩子方法 ,通过钩子方法返回的布尔值来决定是否需要执行模板方法中的某个操作。

钩子方法 的作用主要体现在以下几个方面:

  • 提供默认行为: 钩子方法通常在抽象类中提供了一个默认的实现,这个默认实现可以在模板方法中被调用。如果具体子类选择不覆盖钩子方法,就会使用这个默认行为。这使得在不同的子类中可以有一些通用的行为。

  • 允许选择性的行为扩展: 具体子类可以选择性地覆盖钩子方法,以添加或修改某些行为,以适应特定的需求。这为子类提供了一定的灵活性,使其能够自定义模板方法的部分行为,而不需要修改整个模板方法。

  • 控制模板方法执行流程: 钩子方法的返回值通常被用于在模板方法中控制流程。例如,可以使用钩子方法返回的布尔值来决定是否执行模板方法中的某个步骤。这样,通过覆盖钩子方法,可以在不同的子类中控制模板方法的执行流程。

接下来,我们使用钩子方法对上述例子进行改造,具体实现类如下:

抽象类:

public abstract class AbstractClass {

    //模板方法(定义基本方法的执行顺序)
    public final void service() {

        if (isVIP()) {
            getNum();
            doWait();
        }
        doService();
        doExit();
    }

    //钩子方法
    public boolean isVIP() {
        return false;
    }

    //下面的方法都称为基本方法
    //第一步:取号(一样的,所以直接实现)
    public void getNum() {
        System.out.println("取号");
    }

    //第二部:排队(一样的,所以直接实现)
    public void doWait() {
        System.out.println("排队");
    }

    //第三步:办理具体业务(不一样,由子类实现)
    public abstract void doService();

    //第四步:离开银行(一样的,所以直接实现)
    public void doExit() {
        System.out.println("离开银行");
    }
    
}

存款业务类:

public class SaveMoney extends AbstractClass {

    public void doService() {
        System.out.println("办理存款业务");
    }

    //覆盖钩子方法
    @Override
    public boolean isVIP() {
        return true;
    }
}

取款业务类:

public class TakeMoney extends AbstractClass  {
    
    public void doService() {
        System.out.println("办理取款业务");
    }
}

客户端类:

public class client {

    public static void main(String[] args) {

        //办理存款业务
        SaveMoney saveMoney = new SaveMoney();
        saveMoney.service();

        System.out.println("---------------");

        //办理取款业务
        TakeMoney takeMoney = new TakeMoney();
        takeMoney.service();
    }

}

测试结果:
在这里插入图片描述


五、模板方法模式的优缺点

优点:

  • 提高代码服复用性 : 将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中。
  • 实现了反向控制 : 通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 ,并符合“开闭原则”。

缺点:

  • 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

六、模板方法模式的使用场景

  • 算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
  • 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。


非常感谢您阅读到这里,如果这篇文章对您有帮助,希望能留下您的点赞???? 关注???? 分享???? 留言????thanks!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java设计模式:模板方法模式 的相关文章

  • 如何自定义BlockingQueue的阻塞行为

    我想创建一个阻塞队列 它根据自定义规则而不是队列中的项目数量来阻止生产者 例如 生产者生成一些文件并放入队列中 消费者经过一番分析后将它们转移到特定位置 对于上述场景 如果队列中的总文件大小达到某个阈值 我希望生产者等待生成新文件 如果总大
  • Java/JAXB:将具有相同名称但不同属性值的 XML 元素解组到不同的类成员

    我正在尝试根据其属性之一将具有多个 Fields 元素的 XML 解析为不同的类成员 这是 XML
  • 如何在 OpenAPI 3.0 中定义字节数组

    我正在将 API 从 Swagger 2 0 迁移到 OpenAPI 3 0 在 DTO 中 我有一个指定为字节数组的字段 Swagger 对 DTO 的定义 Job type object properties body type str
  • Java:检查给定日期是否在当前月份内

    我需要检查给定的日期是否在当前月份 我编写了以下代码 但 IDE 提醒我getMonth https docs oracle com javase 7 docs api java util Date html getMonth and ge
  • 无法从后台服务通过 WiFi 访问互联网

    我将直接介绍我发现的一些事实 数据 如果您遇到 解决了类似的问题 请帮助我 我每 5 分钟向服务器发送一次数据 除非用户在服务器的帮助下手动将其关闭 wakeful broadcast receiver通过一个intent service
  • 独占锁定ConcurrentHashMap

    我知道不可能锁定 ConcurrentHashMap 进行独占访问 但是 我找不到原因 是因为构成CHM的 Segment 没有被api公开吗 据推测 如果是的话 客户端代码可以执行 交接 锁定 Cheers 我知道不可能锁定 Concur
  • 会话 bean 中的 EntityManager 异常处理

    我有一个托管无状态会话 bean 其中注入了 EntityManager em 我想做的是拥有一个具有唯一列的数据库表 然后我运行一些尝试插入实体的算法 但是 如果实体存在 它将更新它或跳过它 我想要这样的东西 try em persist
  • LibGdx 如何使用 OrthographicCamera 滚动?

    我已经找了 10 个小时 字面意思 我已经完成了 我需要问一下 事情是我正在学习如何使用 LibGdx 来编写 Java 游戏 我正在做一个水平太空飞船游戏 所以 我最糟糕的问题是我不知道如何滚动 我认为绘制会更好地解释 我想绘制一个巨大的
  • 在 Mac 上使用 JRE 打开 jar 文件

    我有一个 jar 文件 旨在通过命令行运行 我不打算在运行应用程序的机器上进行任何java开发 我的思考过程是 因此我应该只需要JRE而不是JDK 此外 JDK 大约是 JRE 的 4 倍 我不想下载它 在 Mac 上安装 JRE 时 它不
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • java 属性文件作为枚举

    是否可以将属性文件转换为枚举 我有一个包含很多设置的属性文件 例如 equipment height equipment widht equipment depth and many more like this and not all a
  • 使用外部硬盘写入和存储 mysql 数据库

    我已经设置了 mysql 数据库在我的 Mac 上使用 java 和 eclipse 运行 它运行得很好 但现在我将生成大约 43 亿行数据 这将占用大约 64GB 的数据 我存储了大量的密钥和加密值 我有一个 1TB 外部我想用作存储位置
  • 通用 JSF 实体转换器[重复]

    这个问题在这里已经有答案了 我正在编写我的第一个 Java EE 6 Web 应用程序作为学习练习 我没有使用框架 只是使用 JPA 2 0 EJB 3 1 和 JSF 2 0 我有一个自定义转换器 用于将存储在 SelectOne 组件中
  • java中的比较器链

    正在阅读Oracle 关于接口的 Java 教程 https docs oracle com javase tutorial java IandI createinterface html其中给出了一个例子Card 打牌 我试图理解接口中的
  • 将字符串中的字符向左移动

    我是 Stack Overflow 的新手 有一道编程课的实验室问题一直困扰着我 该问题要求我们将字符串 s 的元素向左移动 k 次 例如 如果输入是 Hello World 和3 它将输出 lo WorldHel 对于非常大的 k 值 它
  • JDK 7 的快速调试/调试构建

    我正在寻找 JDK 的调试 或者我猜他们称之为快速调试构建 以启用在运行时生成的打印程序集以及查找性能问题时所需的其他诊断 就目前情况而言 我似乎找不到可以直接使用的 现成的 快速调试构建二进制包 有人可以帮我提供下载链接 或者至少提供有关
  • Java的hashCode可以为不同的字符串产生相同的值吗?

    使用java的哈希码函数是否可以为不同的字符串提供相同的哈希码 或者如果可能的话 其可能性的 是多少 Java 哈希码是 32 位 它散列的可能字符串的数量是无限的 所以是的 会发生冲突 百分比是没有意义的 项目 字符串 的数量是无限的 而
  • Java泛型类型

    当我有一个界面时 public interface Foo
  • Java 9 中紧凑字符串和压缩字符串的区别

    有什么优点紧凑的字符串 http openjdk java net jeps 254JDK9 中的压缩字符串 压缩字符串 Java 6 和紧凑字符串 Java 9 都有相同的动机 字符串通常实际上是 Latin 1 因此浪费了一半的空间 和
  • 如何在Java中跨类共享变量,我尝试了静态不起作用

    类 Testclass1 有一个变量 有一些执行会改变变量的值 现在在同一个包中有类 Testclass2 我将如何访问 Testclass2 中变量的更新值 由 Testclass1 更新 试过这个没用 注意 Testclass1和Tes

随机推荐

  • 基于springboot的高校毕业生就业推荐系统【论文、源码、开题报告】

    博主介绍 全网个人号和企业号 粉丝40W 每年辅导几千名大学生较好的完成毕业设计 专注计算机软件领域的项目研发 不断的进行新技术的项目实战 热门专栏 推荐订阅 订阅收藏起来 防止下次找不到 千套JAVA实战项目持续更新中 上百套小程序实战项
  • C++中的并发多线程网络通讯

    C 中的并发多线程网络通讯 一 引言 C 作为一种高效且功能强大的编程语言 为开发者提供了多种工具来处理多线程和网络通信 多线程编程允许多个任务同时执行 而网络通信则是现代应用程序的基石 本文将深入探讨如何使用C 实现并发多线程网络通信 并
  • 在一个线程池中,通常无法直接访问和检查单个线程的状态,因为线程池是由多个线程组成的,并且线程的执行情况可能会动态变化

    在一个线程池中 通常无法直接访问和检查单个线程的状态 因为线程池是由多个线程组成的 并且线程的执行情况可能会动态变化 然而 你可以通过一些方法来间接地查看线程是否在运行 一种常见的方法是为线程池中的每个线程设置一个标志或状态变量 用于表示线
  • 【java】将本地jar包引入到maven项目中

    两种方式 1 将jar包打入maven仓库 再通过pom引入jar 2 本地pom中引入 方法一 将jar包打入maven仓库 再通过pom引入jar mvn install install file Dfile jar包的位置 Dgrou
  • R语言——基本操作(一)

    目录 一 基本操作 二 R包的安装及使用 三 获取帮助 四 内置数据集 五 数据结构 六 向量索引 七 向量运算 参考 Rstudio 控制台常用快捷键 Ctrl 查看所有历史记录 比直接使用 查找更方便 Esc 中断操作 可中断未完成的操
  • 热烈祝贺怿星科技荣获高工智能汽车产业链TOP100奖

    2023 第七届 高工智能汽车年会 2023 12 14 2023年12月14日 以 寻找拐点 为主题的2023 第七届 高工智能汽车年会在上海隆重举行 怿星科技受邀参加本次会议 并获得智能汽车产业链TOP100创新企业奖 创新企业TOP1
  • ASF-YOLO:一种基于注意尺度序列融合的细胞实例分割YOLO模型

    摘要 我们提出了一种基于注意力尺度序列融合的You Only Look Once YOLO 框架 ASF YOLO 该框架结合了空间和尺度特征 用于准确快速的细胞实例分割 在YOLO分割框架的基础上 我们采用尺度序列特征融合 SSFF 模块
  • 【计算机毕业设计】基于微信小程序的家具购物小程序

    随着信息技术在管理上越来越深入而广泛的应用 管理信息系统的实施在技术上已逐步成熟 本文介绍了基于微信小程序的家具购物小程序的设计与实现的开发全过程 通过分析基于微信小程序的家具购物小程序的设计与实现管理的不足 创建了一个计算机管理基于微信小
  • 【计算机毕业设计】外卖小程序

    随着科技的进步 微信小程序慢慢进入了生活当中 由于轻便快捷 方便使用 基于微信这个大平台 使得小程序飞速发展 趋于成熟 因此 针对用户对外卖点餐方面的需求 特开发了本外卖小程序 该外卖小程序分为小程序前端和Java后端系统 遵循数据前后端交
  • YoloV7改进策略:双动态令牌混合器(D-Mixer)的TransXNet,实现YoloV7的有效涨点

    摘要 双动态令牌混合器 D Mixer 一种输入依赖的方式聚合全局信息和局部细节 D Mixer通过分别在均匀分割的特征片段上应用有效的全局注意力模块和输入依赖的深度卷积 使网络具有强大的归纳偏差和扩大的有效感受野 使用D Mixer作为基
  • 【计算机毕业设计】基于微信小程序的电子购物系统

    由于APP软件在开发以及运营上面所需成本较高 而用户手机需要安装各种APP软件 因此占用用户过多的手机存储空间 导致用户手机运行缓慢 体验度比较差 进而导致用户会卸载非必要的APP 倒逼管理者必须改变运营策略 随着微信小程序的出现 解决了用
  • 我的创作纪念日-IT从业者张某某

    机缘 勿忘初心 牢记使命 我成为创作者的初心是什么呢 时间有些久了 回头看下自己的第一篇博客 还是略显青涩的 有种不忍直视的感觉 我的第一篇博客 应该是想记录下工作中的一个演示项目 并想着把这个演示项目通过文章的方向进行记录下来 便于和团队
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • Js new Date() 年月日时分秒的日期时间格式排序

    new Date 日期对象 效果 排序前 2023 12 10 12 01 21 2023 12 10 18 53 09 2023 12 10 08 10 12 2023 12 10 00 06 06 2023 12 10 16 36 08
  • 关于“Python”的核心知识点整理大全26

    目录 10 3 9 决定报告哪些错误 10 4 存储数据 10 4 1 使用 json dump 和 json load number writer py number reader py 10 4 2 保存和读取用户生成的数据 对于用户生
  • 在AI技术的无情侵袭下,学学Java的23种设计模式还是非常有必要的

    目前国内80 程序员的主要工作是调用组合api实现各种业务需求 在顶层架构师设定好的框架下 做着重复且无聊的编码工作 如果未来ai被广泛应用 那么被替代的风险是很高的 比较扎心的是 其实目前用ai生成片段代码已经是各个公司比较普遍的做法了
  • 【计算机毕业设计】南宁周边乡村游

    随着我国经济迅速发展 人们对手机的需求越来越大 各种手机软件也都在被广泛应用 但是对于手机进行数据信息管理 对于手机的各种软件也是备受游客的喜爱 南宁周边乡村游被游客普遍使用 为方便游客能够可以随时进行南宁周边乡村游的数据信息管理 特开发了
  • Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

    功能描述 1 门户管理 所有用户可在门户页面查看所有的公告信息及相关的通知信息 主要板块包含 招标公告 非招标公告 系统通知 政策法规 2 立项管理 企业用户可对需要采购的项目进行立项申请 并提交审批 查看所有的立项信息 主要功能包含 招标
  • 网络攻击3——拒绝服务攻击与缓冲区溢出攻击

    目录 拒绝服务攻击 拒绝服务攻击介绍 分布式拒绝服务攻击介绍 CDN 软件缺陷漏洞 缓冲区溢出 其它高级攻击 拒绝服务攻击 拒绝服务攻击不会破坏信息的机密性和完整性 而是破坏服务的可用性 拒绝服务攻击分为两大类 DoS 拒绝服务攻击 DDo
  • Java设计模式:模板方法模式

    作者主页 欢迎来到我的技术博客 个人介绍 大家好 本人热衷于 Java后端开发 欢迎来交流学习哦 如果文章对您有帮助 记得 关注 点赞 收藏 评论 您的支持将是我创作的动力 让我们一起加油进步吧 文章目录 一 模板方法模式的定义 二 模板方