设计模式——模板方法模式

news2024/10/6 4:43:02

是什么?

        在我们的实际开发中尝尝会遇到这种问题:在设计一个系统时知道了算法所需要的关键步骤,而且确定了这些步骤的执行顺序,但是某些步骤的具体实现还不知道,或者说某些步骤的实现与具体的环境相关,例如每个人订车,最开始的流程都是相同的:预约、到店、取号、排队、办理业务,这些流程对于每个客户都是相同的,但是办理业务这个流程对于每个客户都可能是不同的,比如有的客户是来订车,有的客户是来进行保养,而有的客户是来更换配饰;

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

结构

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

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

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

        抽象方法:一个抽象方法由抽象类声明、由其具体子类实现;

        具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承;

        钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种,一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXxx,返回值为boolean类型;

具体子类:实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤;

实现

抽象类

public abstract class TemplateAbstractCar {

    /**
     * 模板方法模式中的抽象类
     * 已经实现的方法均为基本方法
     * */
    //预约服务
    public void book(){
       System.out.println("预约服务");
   };
   //到店服务
   public void arrival(){
       System.out.println("客户到店");
   };
   //取号
    public void takeNumber(){
        System.out.println("客户取号");
    };
    //排队服务
    public void line(){
        System.out.println("客户排队");
    }
    //客户具体操作
    protected abstract void buyCar();

    protected  boolean isBuyCar(){
        return false;
    };

    protected abstract void maintain();

    protected boolean isMaintain(){
        return false;
    };

    //空方法
    public void hook(){

    }
    public final void run(){
        //启动四个基本方法
        book();
        arrival();
        takeNumber();
        line();
        //根据子类是否实现了具体方法和钩子方法来判断是否启动
        if (isBuyCar()){
            buyCar();
        }
        if (isMaintain()){
            maintain();
        }
        hook();
    }
}

具体子类

public class Customer extends TemplateAbstractCar{
    @Override
    protected void buyCar() {
        System.out.println("客户1买车服务完毕");
    }

    @Override
    protected void maintain() {

    }

    @Override
    protected boolean isBuyCar() {
        return true;
    }
}

public class Customer2 extends TemplateAbstractCar{
    @Override
    protected void buyCar() {

    }

    @Override
    protected void maintain() {
        System.out.println("客户2保养服务完成");
    }

    @Override
    protected boolean isMaintain() {
        return true;
    }

    @Override
    public void hook() {
        System.out.println("客户二最后还回来买了一辆车");
    }
}

优缺点

   优点

1.提高代码的复用性,将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中;

2.实现了反向控制,通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制,并符合“开闭原则”;

   缺点

1.对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象;

2.父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度;

使用场景

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

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

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

相关文章

CypherRat使用

cypherrat3.5 安卓远控,很早之前在tg下的,现在可能有高版本的 使用感受 图形化界面(相比于msf)可用于演练新场景,实战的话只能用xx破解版或是瑟瑟apk让人忽视风险继续安装由于国内安卓,部分功能失效 生成…

Android 拍照以及相册中选择(适配高版本)————上传多张照片之压缩处理、在线预览可伸缩放大(二)

______ Introduction ______ 前言 上一篇文章刚给大家总结完,关于上传头像的功能。此文章所述 主要是关于上传头像的具体流程以及如何对照片做裁剪处理,回调给控件显示;当然重中之重适配了Android高版本,有兴趣的大家可以去看一下…

PyQt5桌面应用开发(6):文件对话框

本文目录 PyQt5桌面应用系列介绍QFileDialog的静态接口QFileDialog的对象接口 示例结论后记 PyQt5桌面应用系列 PyQt5桌面应用开发(1):需求分析 PyQt5桌面应用开发(2):事件循环 PyQt5桌面应用开发&#xff…

linux安装node_exporter

下载 Download | Prometheus 解压 tar xvzf node_exporter-1.5.0.darwin-amd64.tar.gz 解压后有三个文件,分别是LICENSE、node_exporter、NOTICE 将node_exporter移动到/etc下 mv mode_exporter /etc/systemd/system 创建node_exporter.service文件 touch node_exp…

基于matlab模拟雷达接收机测试信号

一、前言 本例展示了如何模拟单基地脉冲雷达的接收信号以估计目标范围。单基地雷达将发射器与接收器并置。发射器产生一个脉冲,该脉冲击中目标并产生接收器接收的回波。通过测量回波在时间上的位置,我们可以估计目标的范围。 本示例重点介绍脉冲雷达系统…

【线程安全】死锁问题及解决方案

1. 什么是死锁 比如上一次讲到 synchronized 的时候,一个线程,对同一个对象连续加锁两次,如果出现阻塞等待,代表这个锁是不可重入锁,这样的线程,也就称为死锁! 一旦程序进入死锁了就会导致线程僵…

低代码开发重要工具:JVS列表页字段样式配置说明

列表页中,通常存在各种各样的样式控制,例如字段宽度需要可调、字段的颜色根据内容变化等,那么我们接下来介绍下字段的样式控制的内容以及对应的效果。 1、字段样式控制配置位置 进入列表页的 数据配置界面,每个字段可以有独立的配…

在外远程控制我的世界服务器 - MCSM面板【端口映射】

文章目录 概述1.MCSManager 安装2.内网穿透2.1 安装cpolar内网穿透 3. 访问公网地址4.固定公网地址4.1 保留一个二级子域名4.2 配置固定二级域名4.3 访问固定公网地址 5. 设置节点公网地址6. 固定节点公网地址6.1 保留一个固定tcp地址6.2 配置固定TCP地址 转载自远程穿透文章&a…

从零开始学习Linux运维,成为IT领域翘楚(七)

文章目录 🔥Linux下常用软件安装_JDK和Tomcat安装🔥Linux下常用软件安装_MySQL安装🔥Linux下常用软件安装_MySQL卸载 🔥Linux下常用软件安装_JDK和Tomcat安装 Jdk 安装 解压jdk安装包 tar -zxvf jdk-8u201-linux-x64.tar.gz -C/…

中国核心生态区类型及土地利用数据有哪些,如何进行获取

全国生态功能区划是在全国生态调查的基础上,分析区域生态特征、生态系统服务功能与生态敏感性空间分异规律,确定不同地域单元的主导生态功能,制定全国生态功能区划,对贯彻落实科学发展观,牢固树立生态文明观念&#xf…

顺序存储二叉树线索化二叉树

顺序存储二叉树&线索化二叉树 文章目录 顺序存储二叉树&线索化二叉树顺序存储二叉树介绍代码实现 线索化二叉树介绍代码实现 顺序存储二叉树 介绍 背景:从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树…

我把大厂起诉了,协商拿了2N,整理点经验心得给大家,关于离职时如何让自己利益最大化!...

离职时,如何让自己的利益最大化? 一位跟大厂仲裁,并通过协商拿到2n的网友分享了自己的经验心得,干货满满,下面是要点总结: 1.大部分裁员都是违法裁员,应该给2n,但公司不会承认&#…

排序算法 — 归并排序

文章目录 归并排序介绍从下往上的归并排序从上往下的归并排序 归并排序实现从上往下的归并排序从下往上的归并排序 归并排序的时间复杂度和稳定性归并排序时间复杂度归并排序稳定性 代码实现核心&总结 每日一道算法,提高脑力。第五天(时隔7天,终于回…

mac下用git客户端生成ssh秘钥并配置到souretree进行使用

一、使用git 生成 ssh 密钥 1、Mac 安装 git 客户端 打开终端,执行命令: $ brew install git2、执行命令 $ git config --global user.name "xxx" 你自己的名字 $ git config --global user.email "xxxxxx.com&q…

Educational-Codeforces-Round-147-Rated-for-Div-2

title: Educational Codeforces Round 147 (Rated for Div. 2) date: 2023-04-21 15:47:29 categories: AlgorithmCodeforces tags:codeforcesdiv2 Educational Codeforces Round 147 (Rated for Div. 2) A. Matching 题目大意 给你一个字符串,里面包含数字和?,…

Redis缓存穿透和雪崩

Redis缓存穿透和雪崩 Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题…

AI 工具合辑盘点(七)持续更新 之 AI 音频生成工具

AI 音频生成工具 想要不亲自录制,快速将文本转换为语音?AI 音频生成工具为你提供数千种语音选择,从“普通人”的声音到模仿演员、政治家或电影角色的合成声音,各种声音应有尽有 🗣 AI 音频生成工具可用于创建商业用途…

模糊PID模糊控制(清晰化方法梯形图实现)

模糊PID的模糊化请参看下面的博客文章: 博途PLC模糊PID三角隶属度函数指令(含Matlab仿真)_plc 模糊pid_RXXW_Dor的博客-CSDN博客三角隶属度函数FC,我们采用兼容C99标准的函数返回值写法,在FB里调用会更加直观,下面给大家具体讲解代码。常规写法的隶属度函数FC可以参看下…

Python小姿势 - Python中的列表推导式

Python中的列表推导式 Python中的列表推导式是一种很好的创建列表的方式。它允许你将一个操作应用于列表中的每个元素,并将结果放入一个新的列表中。 例如,假设你有一个包含数字的列表,但是你想将每个数字都乘以2,并将结果放入一个…

第三十二章 Unity Mecanim动画系统(上)

在上一章节中,我们介绍了Unity的旧版动画系统,本章节来介绍新版的Mecanim动画系统。新版的Mecanim动画系统实际是对旧版动画系统的升级。新版的Mecanim动画系统仍然是建立在动画片段的基础上的,只不过它给我们提供了一个可视化的窗口来编辑动…