设计模式使用场景实现示例及优缺点(行为型模式——模板方法模式)
模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法的骨架,将算法的一些步骤延迟到子类中。这样可以在不改变算法的结构的前提下,重新定义算法的某些特定步骤。
核心组件
- AbstractClass(抽象类):这是一个抽象基类,它定义了一套算法的模板。它实现了模板方法,定义了算法的骨架,具体步骤由子类实现。
- ConcreteClass(具体类):这些类继承自抽象基类,并实现其算法中的具体步骤。
适用场景
- 一次性实现算法的不变部分:
- 当算法的大部分结构固定不变,但某些步骤具有多变性时,可使用模板方法模式。
- 各子类中公共行为应提取到单一位置避免代码重复:
- 通过模板方法模式,可以将公共行为提取到超类中,通过继承机制复用这部分代码。
- 控制子类扩展:
- 模板方法模式通过将算法的核心流程固化在超类中,防止子类破坏原有算法的结构。
实现实例
以一个简单的游戏开发为例,其中游戏的基本结构(启动、开始、结束)是固定的,但具体每个阶段的实现可以根据不同类型的游戏变化。使用模板方法模式可以固定游戏的主体流程,而将具体步骤的实现留给子类:
抽象类(Abstract Class)
这个类定义了游戏的基本流程,并将具体实现留给子类。
public abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();// 模板方法public final void play() {initialize(); // 初始化游戏startPlay(); // 开始游戏endPlay(); // 结束游戏}
}
具体类(Concrete Classes)
这些类继承自抽象基类,并实现了其具体的操作。
public class Cricket extends Game {@Overridevoid initialize() {System.out.println("Cricket Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Cricket Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Cricket Game Finished!");}
}public class Football extends Game {@Overridevoid initialize() {System.out.println("Football Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Football Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Football Game Finished!");}
}
客户端代码(Client Code)
这部分代码演示了如何使用模板方法模式来规范游戏的流程。
public class Client {public static void main(String[] args) {Game game = new Cricket();game.play(); // 按照Cricket的流程执行游戏game = new Football();game.play(); // 按照Football的流程执行游戏}
}
优缺点
优点
- 提高代码复用性:
- 将通用部分的代码放在抽象的父类中,减少了子类的重复代码。
- 扩展性好:
- 新增具体类时,只需实现算法的可变部分,不需修改已有的代码。
- 控制子类扩展:
- 可以在超类中定义严格的算法规则,限定子类的行为和结构。
缺点
- 对继承的依赖:
- 模板方法模式通过继承来实现,可能会导致过多的类层次。
- 可能违背Liskov替换原则:
- 如果子类不适当地实现父类的方法,可能会违背Liskov替换原则。
类图
+----------------+ +------------------+
| AbstractClass|-------->| ConcreteClass |
+----------------+ +------------------+
| + templateMethod() | + step1() |
| + step1() | + step2() |
| + step2() +------------------+
| + step3() |
+----------------+ |
| + step3() |
+----------------+ ||+-------------------+|| |
+---------------+ +-----------------+
|ConcreteClassA | |ConcreteClassB |
+---------------+ +-----------------+
| + step1() | | + step1() |
| + step2() | | + step2() |
| + step3() | | + step3() |
+---------------+ +-----------------+
注意事项
设计灵活性与复杂性:
模板方法模式虽然提高了代码的复用性,但也可能导致设计过于复杂。在设计时应确保不过度使用,以免造成系统的不必要复杂。
子类的设计约束:
子类实现时必须遵循抽象基类的方法模板,这限制了子类的灵活性。设计者需要在提供足够的灵活性和维持算法结构之间找到平衡。
重构与维护:
如果模板方法本身需要修改,可能会影响到所有的子类。因此,在模板方法中应尽量减少修改的可能性,确保长时间的稳定性。
总结
模板方法模式是一种强大的设计工具,通过预定义算法的结构,提供了高度的复用性和扩展性。它不仅适用于软件开发,还广泛应用于系统设计和业务流程管理。通过对模式的适当扩展和优化,可以有效应对更加复杂和动态的设计挑战。这种模式的成功实施需要深入理解业务需求和技术上的灵活运用,以确保设计的可维护性和系统的可扩展性。
相关文章:
设计模式使用场景实现示例及优缺点(行为型模式——模板方法模式)
模板方法模式(Template Method Pattern) 模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法的骨架,将算法的一些步骤延迟到子类中。这样可以在不改变算法的结构的前提下…...

ETL数据集成丨主流ETL工具(ETLCloud、DataX、Kettle)数据传输性能大PK
目前市面上的ETL工具众多,为了方便广大企业用户在选择ETL工具时有一个更直观性能方面的参考值,我们选取了目前市面上最流行的三款ETL工具(ETLCloud、DataX、Kettle)来作为本次性能传输的代表,虽然性能测试数据有很多相…...

eNSP:防火墙设置模拟公司配置(二)
实验拓扑: 实验要求(二): 7: 办公设备可以通过电信连接和移动上网(多对多NAT,并且需要保留一个公网IP) 8: 分公司通过公网移动电信,访问DMZ的http服务器 9&a…...
vue3 两个组件之间传值
Props 父组件可以通过 props 将数据传递给子组件。这是最常见的组件间通信方式 <!-- 父组件 --><template><ChildComponent :message"parentMessage" /></template><script>import ChildComponent from ./ChildComponent.vue;export…...
基于matlab的深度学习案例及基础知识专栏前言
专栏简介 内容涵盖深度学习基础知识、深度学习典型案例、深度学习工程文件、信号处理等相关内容,博客由基于matlab的深度学习案例、matlab基础知识、matlab图像基础知识和matlab信号处理基础知识四部分组成。 一、 基于matlab的深度学习案例 1.1、matlab:基于模…...

机器学习——L1 L2 范数 —>L1 L2正则化
1、L1范数和L2范数是机器学习和数据分析中经常使用的两种范数,它们之间存在多个方面的区别。 以下是关于L1范数和L2范数区别的详细解释: 一、定义差异 L1范数:也被称为曼哈顿范数,是向量元素的绝对值之和。对于一个n维向量x&am…...
大模型时代,还需要跨端framework吗?
跨端 在我近十年的大前端从业经验中,有一半是在和flutter/rn打交道。虽然,flutter和rn官方和社区已经在非常努力的优化、填坑了,但是这两者的坑还是远远高于原生开发。 但是,在锁表的大周期下,华为带着鸿蒙来了&#…...

ASP.NET Core----基础学习05----将数据传递给视图文件的五种情况
文章目录 1. 类型一:使用ViewData将数据传递给视图文件(默认视图文件)2. 类型二:自定义选择视图文件 并传递ViewData数据3. 类型三:使用ViewBag将数据传递给视图文件4. 类型四:在视图文件中使用model转化为…...

Flutter实现局部刷新的几种方式
目录 前言 1.局部刷新的重要性 1.概念 2.重要性 2.局部刷新实现的几种方式 1.使用setState方法进行局部刷新 2.使用StatefulWidget和InheritedWidget局部刷新UI 3.ValueNotifier和ValueListenableBuilder 4.StreamBuilder 5.Provider 6.GetX 7.使用GlobalKey 前言 …...
力扣题解(回文子串)
647. 回文子串 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 思路: 首先,本题要求的是数目,而且不要求没…...

对数的基本概念
概念 在数学中,对数是对求幂的逆运算,正如除法是乘法的倒数,反之亦然。这意味着一个数字的对数是必须产生过另一个固定数字(基数)的指数 如果a的x次方等于N(a > 0, 且a不等于1),那么数x叫做以a为底N的…...

C双指针滑动窗口算法
这也许是双指针技巧的最⾼境界了,如果掌握了此算法,可以解决⼀⼤类⼦字符串匹配的问题 原理 1、我们在字符串 S 中使⽤双指针中的左右指针技巧,初始化 left right 0,把索引闭区间 [left, right] 称为⼀个「窗⼝」。 2、我们先…...

WPF学习(6) -- WPF命令和通知
一 、WPF命令 1.ICommand代码 创建一个文件夹和文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input;namespace 学习.Command {public class MyCommand : ICommand{Acti…...

升级到LVGL9的一些变化(后续发现再补充)
目录 一、主要内容 二、新增内容 三、常规API变化 四、Display API(显示API) 五、其他 最近在将LVGL8的demo代码升级到LVGL9,带来不小的变化 ,收集网上的一些内容,整理如下: 一、主要内容 二、新增内容 三、常规API变化 四、Display API(显示API)...
当在多线程环境中使用 C++进行编程时,怎样确保线程安全以及如何处理线程之间的同步和通信?
在C中确保线程安全性和处理线程之间的同步和通信有多种方法。下面是一些常用的技术和技巧: 互斥锁:使用互斥锁可以确保只有一个线程可以访问共享资源。在访问共享资源之前获取锁,在完成后释放锁。这可以防止多个线程同时访问同一份数据&#…...

博物馆地图导航系统:高精度地图引擎与AR/VR融合,实现博物馆数字化转型
在人民日益追求精神文化的时代下,博物馆作为传承与展示人类文明的璀璨殿堂,其重要性不言而喻。然而,随着博物馆规模的不断扩大和藏品种类的日益丰富,游客在享受知识盛宴的同时,也面临着“迷路”与“错过”的困扰。博物…...
liunx作业笔记1
一、选择题(每小题2分,共20分) 1、下列变量命名为Shell中无效变量名的是( D ) A、v_ar1 B、var1 C、_var D、*var 变量名以字母开头,包含下划线和数字。 2、关于expr命令的使用下列命令中得数不等于…...
大话C语言:第31篇 指针和数组的关系
数组在内存中是连续存放的,其名称代表了数组首元素的首地址,该地址是常量, 也就是一个指向数组首元素的指针。因此,指针和数组有着密切的关系: 可以使用指针来访问和操作数组中的元素。通过指针的算术运算,…...
Mysql-索引应用
目录 索引应用 MySQL有哪些索引? 普通索引和唯一索引有什么区别? 哪个更新性能更好? 、 聚簇索引的主键索引怎么设置? 追问:假如你不设置会怎么样? 我们一般选择什么样的字段来建立索引? 索引越多越好吗? 索引怎么优化? (覆盖索引优化、防止索引失效、…...

Facebook 开源计算机视觉 (CV) 和 增强现实 (AR) 框架 Ocean
Ocean 是一个独立于平台的框架,支持所有主要操作系统,包括 iOS、Android、Quest、macOS、Windows 和 Linux。它旨在彻底改变计算机视觉和混合现实应用程序的开发。 Ocean 主要使用 C 编写,包括计算机视觉、几何、媒体处理、网络和渲染&#x…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...