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

文章目录

  • 一:模板方法设计模式概述
    • 1.1 简介
    • 1.2 定义和目的
    • 1.3 关键特点
    • 1.4 适用场景
  • 二:模板方法设计模式基本原理
    • 2.1 抽象类
      • 2.1.1 定义和作用
      • 2.1.2 模板方法
      • 2.1.3 具体方法
    • 2.2 具体类
      • 2.2.1 定义和作用
      • 2.2.2 实现抽象类中的抽象方法
      • 2.2.3 覆盖钩子方法
  • 三:模板方法设计模式实现步骤
    • 3.1 创建抽象类
      • 3.1.1 声明模板方法
      • 3.1.2 定义具体方法
      • 3.1.3 定义钩子方法
    • 3.2 创建具体类
      • 3.2.1 实现抽象类中的抽象方法
      • 3.2.2 覆盖钩子方法
  • 四:模板方法设计模式应用场景
    • 4.1 实际案例背景介绍
    • 4.2 设计模式解决方案
    • 4.3 实现代码示例
  • 五:模板方法设计模式应用注意事项
    • 5.1 钩子方法的使用场景和注意事项
    • 5.2 与其他设计模式的关系
    • 5.3 使用建议和最佳实践
  • 结语

一:模板方法设计模式概述

1.1 简介

模板方法设计模式是一种行为型设计模式,它定义了一个算法的骨架,在其中某些步骤由具体子类来实现。

1.2 定义和目的

模板方法设计模式通过将算法通用部分放在抽象类中,具体实现留给具体子类来完成,以提高代码的复用性和可维护性。
在这里插入图片描述

1.3 关键特点

  • 模板方法:定义算法的骨架,其中某些步骤由具体子类来实现。
  • 具体方法:抽象类中已经实现的方法,子类不能修改。
  • 钩子方法:抽象类中定义的可选方法,具体子类选择性地覆盖,可以改变模板方法的行为。

1.4 适用场景

  • 当算法有固定的结构或步骤,并且步骤之间存在关联性时,可以使用模板方法设计模式。
  • 当需要在不同上下文中应用相似的算法时,可以使用模板方法设计模式。
  • 当希望通过基类来控制子类的行为时,可以使用模板方法设计模式。

二:模板方法设计模式基本原理

2.1 抽象类

2.1.1 定义和作用

抽象类是模板方法设计模式的核心角色,它定义了模板方法和一系列抽象方法,描述算法的结构和步骤。

2.1.2 模板方法

模板方法是抽象类中定义的方法,描述算法的骨架。该方法通常是final类型的,以防止子类对其进行修改。

2.1.3 具体方法

具体方法是抽象类中已经实现的方法,子类不能修改。这些方法通常是模板方法所需要的辅助方法或公共方法。

2.2 具体类

2.2.1 定义和作用

具体类是抽象类的子类,负责实现抽象类中的抽象方法,完成算法的具体实现。

2.2.2 实现抽象类中的抽象方法

具体类需要实现抽象类中定义的抽象方法,完成算法的具体实现。

2.2.3 覆盖钩子方法

具体类可以选择性地覆盖抽象类中定义的钩子方法,以改变模板方法的行为。

三:模板方法设计模式实现步骤

3.1 创建抽象类

3.1.1 声明模板方法

在抽象类中声明模板方法,描述算法的骨架。通常将该方法设置为final类型,防止子类修改。

3.1.2 定义具体方法

在抽象类中定义具体方法,这些方法在模板方法中被调用。这些方法通常是私有或受保护的,不允许子类直接调用。

3.1.3 定义钩子方法

定义可选的钩子方法,根据需要提供默认实现或为空实现。具体子类可以选择性地覆盖这些方法以改变模板方法的行为。

3.2 创建具体类

3.2.1 实现抽象类中的抽象方法

创建具体类并实现抽象类中的抽象方法,完成算法的具体实现。

3.2.2 覆盖钩子方法

具体类可以选择性地覆盖抽象类中的钩子方法,以改变模板方法的行为。

四:模板方法设计模式应用场景

4.1 实际案例背景介绍

假设我们正在开发一个游戏,这个游戏中有多个角色,每个角色都有不同的行为和技能。我们需要设计一个通用的角色创建流程,以确保每个角色的创建过程都符合一定的规范和约束。这就是一个适用于模板方法设计模式的实际案例。

4.2 设计模式解决方案

我们可以使用模板方法设计模式来解决上述问题。首先,我们创建一个抽象类作为角色的基类,其中包含了一个模板方法用于控制角色的创建流程。具体的角色类继承这个抽象类,并实现其中的抽象方法来完成自己特定的行为和技能。

在抽象类中,我们可以定义一些公共的方法,比如角色的初始化方法、资源加载方法等,这些方法已经实现并且不允许子类修改。同时,我们也可以定义一些钩子方法,用于在角色创建的不同阶段插入一些额外的逻辑。

抽象类中的模板方法定义了角色的创建流程,它按照一定的顺序调用了一系列的具体方法和钩子方法。这些具体方法和钩子方法由具体的角色类来实现,根据不同的需求来完成具体的行为和技能。

通过使用模板方法设计模式,我们可以将公共的部分提取到抽象类中,实现了代码的复用和可维护性的提高。同时,具体的角色类也能够灵活地实现自己特定的行为和技能,满足了游戏中多样化的角色需求。

4.3 实现代码示例

下面是一个简单的实现代码示例,演示了如何使用模板方法设计模式来创建游戏角色:

// 抽象类:角色
public abstract class Character {
    // 模板方法:创建角色
    public final void createCharacter() {
        initialize();   // 初始化角色
        loadResources();    // 加载资源
        doSomething();  // 具体行为
        hookMethod();   // 钩子方法
    }
    
    // 具体方法:初始化角色
    private void initialize() {
        System.out.println("Initializing character...");
    }
    
    // 具体方法:加载资源
    private void loadResources() {
        System.out.println("Loading resources...");
    }
    
    // 抽象方法:具体行为
    protected abstract void doSomething();
    
    // 钩子方法:可选的逻辑
    protected void hookMethod() {
        // 默认为空实现,子类可选择性地覆盖
    }
}

// 具体类:战士角色
public class WarriorCharacter extends Character {
    @Override
    protected void doSomething() {
        System.out.println("Warrior is fighting!");
    }
}

// 具体类:法师角色
public class MageCharacter extends Character {
    @Override
    protected void doSomething() {
        System.out.println("Mage is casting spells!");
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        Character warrior = new WarriorCharacter();
        warrior.createCharacter();   // 输出:Initializing character... Loading resources... Warrior is fighting!
        
        Character mage = new MageCharacter();
        mage.createCharacter();  // 输出:Initializing character... Loading resources... Mage is casting spells!
    }
}

在上面的示例中,Character 是抽象类,其中的 createCharacter() 方法是模板方法,控制了角色的创建流程。具体的角色类 WarriorCharacterMageCharacter 继承了 Character 并实现了其中的抽象方法 doSomething(),完成了自己特定的行为。最后,在 Main 类中测试了这两个具体的角色类的创建过程。

通过运行上述代码示例,你可以看到不同角色的创建流程遵循了模板方法定义的骨架,但同时具体的角色类可以根据自身的需求实现不同的行为和技能。这就是模板方法设计模式的应用。

五:模板方法设计模式应用注意事项

5.1 钩子方法的使用场景和注意事项

钩子方法是在模板方法设计模式中的一种特殊方法,它在抽象类中提供了一个默认的空实现,子类可以选择性地覆盖或扩展这个方法。钩子方法的主要作用是允许子类在模板方法的特定点插入自己的逻辑,以实现对算法的定制和扩展。

使用钩子方法可以使得模板方法更加灵活和可扩展,同时也可以避免在抽象类中定义过多的抽象方法,简化了子类的实现。

一般来说,钩子方法的使用场景包括但不限于以下几种情况:

  1. 选择性执行:某些步骤在特定条件下需要执行,而在其他条件下可以跳过,钩子方法可以判断这些条件并决定是否执行相应步骤。
  2. 扩展功能:在模板方法的特定点添加新的逻辑或功能,用于满足不同的需求。
  3. 改变顺序:通过覆盖或扩展钩子方法,改变模板方法中步骤的执行顺序。

在使用钩子方法时,需要注意以下几点:

  1. 钩子方法的命名:钩子方法应该具有描述性的、能够体现其作用的命名,以便子类理解和正确使用。
  2. 钩子方法的默认实现:钩子方法在抽象类中应该有一个默认的空实现,以保证子类可以选择是否覆盖它。
  3. 钩子方法的调用时机:钩子方法应该在适当的时机被调用,以确保它们的逻辑能够正确地插入到模板方法中。

5.2 与其他设计模式的关系

模板方法设计模式与其他设计模式之间存在一些关系和区别。下面是一些常见的与模板方法设计模式相关的设计模式:

  1. 工厂方法模式(Factory Method Pattern):工厂方法模式也是一种创建型设计模式,它将对象的创建延迟到子类中进行。在工厂方法模式中,模板方法用于定义对象的创建过程,具体的产品由子类来实现。可以说,工厂方法模式是模板方法设计模式在创建对象方面的一种应用。
  2. 策略模式(Strategy Pattern):策略模式用于封装一系列的算法,并使它们可以互相替换。在策略模式中,每个算法都是一个独立的类,而模板方法则是在抽象类中定义的一系列步骤。可以说,策略模式是模板方法设计模式在算法封装方面的一种应用。

需要注意的是,模板方法设计模式和以上提到的设计模式并不是相互排斥的关系,它们可以结合使用来解决复杂的问题。在实际开发中,根据具体的需求和场景选择合适的设计模式,能够更好地设计和实现高质量的代码。

5.3 使用建议和最佳实践

以下是一些使用模板方法设计模式的建议和最佳实践:

  1. 合理划分抽象类和具体类:抽象类应该包含公共的行为和模板方法,具体类应该实现自己特定的行为。
  2. 提取公共的方法和逻辑:将公共的方法和逻辑提取到抽象类中,以避免代码的重复和冗余。
  3. 明确模板方法的执行流程:定义好模板方法的执行顺序,并确保每个步骤的执行时机正确。
  4. 合理使用钩子方法:在需要灵活定制或扩展的地方使用钩子方法,但不要滥用。过多的钩子方法可能导致代码难以理解和维护。
  5. 考虑模板方法的可变性:模板方法应该具有一定的可变性,以便子类可以根据自身需要进行定制。但同时也要保持模板方法的稳定性和一致性。

结语

模板方法设计模式是一种行为设计模式,它通过定义一个算法的骨架,在抽象类中封装了算法的主要步骤,并使用抽象方法和钩子方法来实现可变的部分。这种设计模式使得算法的结构保持稳定,而具体的实现细节可以由子类提供。

模板方法设计模式的优势在于:

  1. 提高代码复用性:将共同的代码逻辑封装在抽象类中,可以在不同的子类中共享使用,避免了重复编写相似的代码。
  2. 简化子类实现:通过将算法中的可变部分定义为抽象方法,子类只需要关注自己特定的实现细节,从而简化了子类的实现。
  3. 提供扩展点:通过钩子方法,允许子类在特定的执行点插入自己的逻辑,以实现对算法的定制和扩展。

然而,在使用模板方法设计模式时也需要考虑一些因素和注意事项:

  1. 需要明确模板方法的执行流程和步骤顺序,确保每个步骤的执行时机正确。
  2. 钩子方法应该有默认的空实现,以保证子类可以选择是否覆盖它。
  3. 合理使用钩子方法,不要过度使用,避免引入不必要的复杂性。
  4. 钩子方法的命名应该具有描述性,以便子类理解和正确使用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3.1.6 练习 基于GPA排名计算本专业保研名单

C自学精简教程 目录(必读) GPA概念回顾 平均学分绩点GPA(Grade Point Average)是对一个学生大学学习成绩的综合的衡量指标。 在前面的文章 本科生学分绩点GPA计算 中,我们知道了什么是平均学分绩点GPA,以及如何计算它。 基于GPA给学生排名 现在我们…

OB Cloud助力泡泡玛特打造新一代分布式抽盒机系统

作为中国潮玩行业的领先者,泡泡玛特凭借 MOLLY、DIMOO、SKULLPANDA 等爆款 IP,以及线上线下全渠道营销收获了千万年轻人的喜爱,会员数达到 2600 多万。2022 年,泡泡玛特实现 46.2 亿元营收,其中线上渠道营收占比 41.8%…

ArcGIS Maps SDK for JS(二):MapView简介----创建2D地图

文章目录 1 AMD 引用 ArcGIS Maps SDK for JavaScript2 加载相应模块3 创建地图4 创建 2D 视图 view5 确定页面内容6 CSS 样式7 完整代码 本教程使用 AMD 模块&#xff0c;指导您如何在二维地图视图中创建一个简单的地图。 1 AMD 引用 ArcGIS Maps SDK for JavaScript 在 <…

智慧电力方案:安防监控/视频分析/智能分析网关AI识别技术在电力领域中的应用

一、行业痛点 随着经济的飞速发展&#xff0c;电力已经是人们生活中必不可少的&#xff0c;无论是在生活还是工作中&#xff0c;电的存在都是不可或缺的。但电力的高效运维&#xff0c;一直是一个难题&#xff0c;当前普通的电力运维系统已无法满足人们的管理需求&#xff0c;…

宏基官网下载的驱动怎么安装(宏基笔记本如何安装系统)

本文为大家介绍宏基官网下载的驱动怎么安装宏基笔记本驱动(宏基笔记本如何安装系统)&#xff0c;下面和小编一起看看详细内容吧。 宏碁笔记本怎么一键更新驱动 1. 单击“开始”&#xff0c;然后选择“所有程序”。 2. 单击Acer&#xff0c;然后单击Acer eRecovery Management。…

Hive3第六章:更换引擎

系列文章目录 Hive3第一章&#xff1a;环境安装 Hive3第二章&#xff1a;简单交互 Hive3第三章&#xff1a;DML数据操作 Hive3第三章&#xff1a;DML数据操作(二) Hive3第四章&#xff1a;分区表和分桶表 Hive3第五章&#xff1a;函数 Hive3第六章&#xff1a;更换引擎 文章目…

stable diffusion实践操作-embedding(TEXTUAL INVERSION)

本文专门开一节写图生图相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 中文名为文本反转&#xff0c;可以理解为提示词的集合&#xff0c;提示词打包&#xff0c;可以省略大量的提示词。后缀safetensors&#xff0c;大小几十…

15000字、6个代码案例、5个原理图让你彻底搞懂Synchronized

Synchronized 本篇文章将围绕synchronized关键字&#xff0c;使用大量图片、案例深入浅出的描述CAS、synchronized Java层面和C层面的实现、锁升级的原理、源码等 大概观看时间17分钟 可以带着几个问题去查看本文&#xff0c;如果认真看完&#xff0c;问题都会迎刃而解&…

【CI/CD技术专题】「Docker实战系列」本地进行生成镜像以及标签Tag推送到DockerHub

背景介绍 Docker镜像构建成功后&#xff0c;只要有docker环境就可以使用&#xff0c;但必须将镜像推送到Docker Hub上去。创建的镜像最好要符合Docker Hub的tag要求&#xff0c;因为在Docker Hub注册的用户名是liboware&#xff0c;最后利用docker push命令推送镜像到公共仓库…

实现不同局域网间的文件共享和端口映射,使用Python自带的HTTP服务

文章目录 1. 前言2. 本地文件服务器搭建2.1 python的安装和设置2.2 cpolar的安装和注册 3. 本地文件服务器的发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 数据共享作为和连接作为互联网的基础应用&#xff0c;不仅在商业和办公场景有广泛的应用…

ITIL 4—创建、交付和支持—利用信息和技术创建、交付和支持服务

3.1 集成和数据共享 服务设计通常依赖于多个系统之间的集成&#xff08;integration&#xff09;&#xff0c;在这种情况下&#xff0c;理解集成建模的不同层次相当重要。例如&#xff1a; 应用程序级 应用程序之间是相互交互的。企业级 已集成的应用程序共同提供价值。业务…

无涯教程-JavaScript - GAMMADIST函数

GAMMADIST函数取代了Excel 2010中的GAMMA.DIST函数。 描述 该函数返回伽马分布。您可以使用此功能来研究可能具有偏斜分布的变量。伽马分布通常用于排队分析。 语法 GAMMADIST(x,alpha,beta,cumulative)争论 Argument描述Required/OptionalXThe value at which you want t…

手摸手2-springboot编写基础的增删改查

目录 手摸手2-springboot编写基础的增删改查创建controller层添加service层接口service层实现添加mapper层mapper层对应的sql添加扫描注解,对应sql文件的目录 手摸手2-springboot编写基础的增删改查 创建controller层 实现 test 表中的添加、修改、删除及列表查询接口&#x…

技术领导力实战笔记25

25&#xff5c;用心做好“鼓励式”管理 激发正能量 授权 分工作&#xff1a; 老人干新事&#xff0c;新人干老事&#xff0c;强者干难事&#xff0c;弱者干细事 新人干老事 所谓新人&#xff0c;是对业务产品不了解&#xff0c;对工作流程不清晰的岗位新人。对于新人来说&…

java八股文面试[多线程]——线程间通信方式

多个线程在并发执行的时候&#xff0c;他们在CPU中是随机切换执行的&#xff0c;这个时候我们想多个线程一起来完成一件任务&#xff0c;这个时候我们就需要线程之间的通信了&#xff0c;多个线程一起来完成一个任务&#xff0c;线程通信一般有4种方式&#xff1a; 通过 volat…

解决Linux Ubuntu上安装RabbitMQ服务后的公网远程访问问题,借助cpolar内网穿透技术

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

哈夫曼树与哈夫曼编码

哈夫曼树与哈夫曼编码 哈夫曼树 哈夫曼树又称最优二叉树&#xff0c;这种数据结构主要用于解决一些编码问题&#xff0c;与普通二叉树相比&#xff0c;哈夫曼树在特定场景下能够显著的提高效率。 相关概念 权值&#xff1a;指哈夫曼树叶子节点的权值&#xff0c;例如上图中哈…

07:STM32----ADC模数转化器

目录 1:简历 2:逐次逼近型ADC 3:ADC基本结构 4:输入通道 5:规则组的4种转换模式 1:单次转化,非扫描模式 2:连续转化,非扫描模式 3:单次转化,扫描模式 4:单次转化,扫描模式 6:触发控制 7:数据对齐 8:转化时间 9:校准 10:ADC的硬件电路 A: AD单通道 1:连接图 2:函…

计算机竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

文章目录 0 简介1 二维码检测2 算法实现流程3 特征提取4 特征分类5 后处理6 代码实现5 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖&#xff0c;适合作为竞赛课…

【多线程案例】单例模式(懒汉模式和饿汉模式)

文章目录 1. 什么是单例模式&#xff1f;2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式&#xff1f; 提起单例模式&#xff0c;就必须介绍设计模式&#xff0c;而设计模式就是在软件设计中&#xff0c;针对特殊…