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设计模式:模板方法模式 的相关文章

随机推荐

  • 基于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后端开发 欢迎来交流学习哦 如果文章对您有帮助 记得 关注 点赞 收藏 评论 您的支持将是我创作的动力 让我们一起加油进步吧 文章目录 一 模板方法模式的定义 二 模板方