当前位置: 首页 > article >正文

【设计模式】行为型-模板方法模式

文章目录前言一、概念二、核心结构三、Java 代码实现订单支付流程1. 抽象类定义模板2. 具体子类微信支付3. 具体子类支付宝支付4. 客户端调用四、钩子方法Hook—— 让模板更灵活五、优缺点优点缺点六、应用场景七、模板方法 VS 策略模式八、总结前言在开发中我们经常会遇到业务流程固定、但个别步骤实现不同的场景比如用户注册流程校验、创建、通知、日志、支付流程验签、扣款、回调、日志、数据导入解析、校验、保存、通知。整个流程骨架一样但某几步具体实现不同。如果每个业务都写一套重复代码会造成大量冗余、难以维护。模板方法模式就是专门处理这种固定流程可变步骤的设计模式。一、概念模板方法模式Template Method Pattern是一种行为型设计模式核心思想定义一个算法的骨架流程将某些步骤的具体实现延迟到子类中使得子类可以不改变整体流程结构即可重定义个别步骤。简单理解父类模板定义整个流程的固定步骤与顺序不允许子类改变骨架。子类实现只重写个别可变步骤流程不变。一句话总结父类定骨架子类填细节。二、核心结构AbstractClass抽象类定义模板方法final防止子类重写定义抽象方法子类必须实现定义钩子方法可选重写定义通用方法公共逻辑ConcreteClass具体子类实现抽象方法完成自身业务逻辑。Client客户端直接调用模板方法。三、Java 代码实现订单支付流程场景所有支付流程都固定为 4 步校验参数固定执行支付不同微信/支付宝/银行卡回调通知固定记录日志固定只有第2步不同完美适合模板方法。1. 抽象类定义模板publicabstractclassAbstractPayTemplate{/** * 模板方法固定支付流程 * final 防止子类篡改流程 */publicfinalvoidpay(StringorderId){checkParam(orderId);// 1.固定doPay(orderId);// 2.可变notify(orderId);// 3.固定log(orderId);// 4.固定}// 固定参数校验privatevoidcheckParam(StringorderId){System.out.println(orderId 参数校验通过);}// 抽象子类必须实现支付逻辑protectedabstractvoiddoPay(StringorderId);// 固定回调通知privatevoidnotify(StringorderId){System.out.println(orderId 支付成功回调通知);}// 固定日志privatevoidlog(StringorderId){System.out.println(orderId 支付日志已记录);}}2. 具体子类微信支付publicclassWechatPayextendsAbstractPayTemplate{OverrideprotectedvoiddoPay(StringorderId){System.out.println(orderId 【微信支付】执行扣款);}}3. 具体子类支付宝支付publicclassAliPayextendsAbstractPayTemplate{OverrideprotectedvoiddoPay(StringorderId){System.out.println(orderId 【支付宝支付】执行扣款);}}4. 客户端调用publicclassClient{publicstaticvoidmain(String[]args){AbstractPayTemplatewechatnewWechatPay();wechat.pay(ORDER_001);System.out.println();AbstractPayTemplatealinewAliPay();ali.pay(ORDER_002);}}输出ORDER_001 参数校验通过 ORDER_001 【微信支付】执行扣款 ORDER_001 支付成功回调通知 ORDER_001 支付日志已记录 ORDER_002 参数校验通过 ORDER_002 【支付宝支付】执行扣款 ORDER_002 支付成功回调通知 ORDER_002 支付日志已记录四、钩子方法Hook—— 让模板更灵活钩子方法是默认空实现/返回true的方法子类可以选择性重写控制流程是否执行某一步。示例增加是否需要回调的钩子publicabstractclassAbstractPayTemplate{publicfinalvoidpay(StringorderId){checkParam(orderId);doPay(orderId);// 钩子控制是否执行通知if(needNotify()){notify(orderId);}log(orderId);}// 钩子方法默认需要通知protectedbooleanneedNotify(){returntrue;}// ... 其他不变}子类可以重写钩子publicclassWechatPayNoNotifyextendsAbstractPayTemplate{OverrideprotectedvoiddoPay(StringorderId){System.out.println(orderId 微信支付(无通知));}// 重写钩子关闭通知OverrideprotectedbooleanneedNotify(){returnfalse;}}五、优缺点优点封装不变部分扩展可变部分流程固定不动细节交给子类。代码复用极强公共逻辑只写一次子类只关注差异。符合开闭原则新增流程只需加子类不改模板。行为由父类控制子类实现结构清晰、易于维护。缺点类数量可能增多每个不同实现一个子类父类若出错会影响所有子类过度使用会导致继承层次复杂六、应用场景凡是流程固定、个别步骤不同的场景支付流程微信/支付宝/银行卡用户注册/登录流程数据导入/导出Excel、CSV、XML消息发送短信、邮件、站内信工作流审批发起、审核、通过、驳回经典源码应用Java ServletdoGet/doPostSpringJdbcTemplate、RestTemplateMyBatisBaseExecutorAndroidActivity生命周期七、模板方法 VS 策略模式模板方法基于继承固定流程骨架步骤可变→ 一套流程多种实现策略模式基于组合算法可互换平级替换→ 多套算法自由切换八、总结模板方法模式 固定流程骨架 可变步骤实现核心父类定流程final子类填细节关键模板方法 抽象方法 钩子方法最适合流程固定、重复代码多、差异小的业务是企业级开发中复用率极高的行为型模式

相关文章:

【设计模式】行为型-模板方法模式

文章目录前言一、概念二、核心结构三、Java 代码实现(订单支付流程)1. 抽象类(定义模板)2. 具体子类:微信支付3. 具体子类:支付宝支付4. 客户端调用四、钩子方法(Hook)—— 让模板更…...

筑牢数据安全底座!百度智能云数据库GaiaDB分布式版通过『国密认证』

近日,百度智能云自研的关系型数据库GaiaDB分布式版获得由国家密码管理局商用密码检测认证中心颁发的《商用密码产品认证证书》,通过GM/T 0028《密码模块安全技术要求》安全等级第二级认证。这一认证标志着GaiaDB分布式版密码模块在密码安全设计、密钥管理…...

告别Trello!这款开源看板工具让你的团队协作更高效

1. 为什么你需要一个Trello替代品? 如果你正在使用Trello管理团队项目,可能已经发现了一些痛点。Trello确实简单易用,但随着团队规模扩大或项目复杂度增加,免费版的限制就会显现出来。比如最多只能创建10个看板,每个看…...

Rust重写GNU核心工具集:现代CLI工具的终极指南

Rust重写GNU核心工具集:现代CLI工具的终极指南 【免费下载链接】coreutils 跨平台的 Rust 重写 GNU 核心工具集。 项目地址: https://gitcode.com/GitHub_Trending/co/coreutils 在当今的软件开发领域,命令行工具仍然是系统管理员、开发者和DevOp…...

MacOS上Rust安装全攻略:从权限问题到成功验证(附常见错误解决)

MacOS上Rust安装全攻略:从权限问题到成功验证 最近两年Rust在开发者社区的热度持续攀升,Stack Overflow的年度调查显示它已经连续七年成为"最受喜爱编程语言"。但对于刚接触Rust的Mac用户来说,安装过程可能会遇到一些棘手的权限问题…...

DeepSeek-R1-Distill-Qwen-7B实测:推理能力超强的7B小模型

DeepSeek-R1-Distill-Qwen-7B实测:推理能力超强的7B小模型 1. 模型概述 DeepSeek-R1-Distill-Qwen-7B是DeepSeek团队推出的轻量级推理模型,基于Qwen架构蒸馏而来。这个7B参数规模的模型在保持较小体积的同时,展现了令人印象深刻的推理能力。…...

Teleport 瞬移组件:模态框、全局提示最佳实践

在 Vue3 开发中,我们经常会遇到这样的场景:组件的结构嵌套在某个父组件内,但渲染后却需要「跳出」当前嵌套层级,挂载到页面的指定位置(比如 body 下)—— 最典型的就是模态框、全局提示、加载弹窗等。 如果…...

AI万能分类器零基础入门:5分钟搭建无需训练的文本分类系统

AI万能分类器零基础入门:5分钟搭建无需训练的文本分类系统 1. 引言:为什么选择零样本分类? 想象一下这样的场景:你刚接手一个新项目,需要快速对大量用户反馈进行分类。传统方法要求你收集数据、标注样本、训练模型&a…...

手写 Vue3 自定义指令:防抖、点击外部、权限控制

在 Vue3 开发中,指令(Directive)是一个非常实用的特性,它允许我们在 DOM 元素上添加自定义行为,封装可复用的逻辑。Vue3 内置了 v-model、v-show、v-bind 等常用指令,但在实际开发中,我们经常会…...

Vue3 模板引用 (ref):操作 DOM 与子组件实例 从入门到精通

前言 在 Vue 的数据驱动思想下,我们通常通过修改数据来驱动视图更新,避免直接操作 DOM。但在实际开发中,总会遇到一些非 DOM 不可的场景:比如获取输入框焦点、调用第三方库初始化画布、获取子组件的数据或方法等。 这时候&#xf…...

sklearn Pipeline:特征工程和建模流水线

你一定写过这样的代码:先对年龄做分箱,再对职业做 one-hot,然后把处理好的列拼起来,最后喂给模型。每一步都是散装的 fit_transform,变量名从 X_binned 到 X_encoded 到 X_final,稍不留神就在测试集上用了训…...

解锁Nvidia Tesla A100完整性能:从驱动安装到Fabric Manager服务配置

1. 为什么你的Tesla A100性能被锁住了? 很多朋友第一次拿到Tesla A100显卡时,都会遇到一个奇怪的现象:明明按照常规方法安装了驱动,nvidia-smi也能正常显示显卡信息,但实际跑深度学习训练或者高性能计算任务时&#xf…...

深入解析dlopen:动态库加载的机制与实践

1. 动态库加载的两种方式 在C/C开发中,动态库(Dynamic Library)的使用是提升代码复用性和灵活性的重要手段。动态库加载主要分为隐式链接和显式链接两种方式,它们各有特点,适用于不同场景。 隐式链接是最常见的方式&am…...

仅剩最后3家银行未完成Java Istio全面替换——这份含12类Java Agent冲突检测脚本、4种Sidecar注入模式对比的适配手册即将下线

第一章:Java Istio适配现状与收官倒计时Istio 1.20 是最后一个官方支持 Java 客户端(istio-java-api)的版本,自 1.21 起,Istio 社区正式移除了对 Java SDK 的维护和 CI 验证。这一决策标志着 Java 生态在 Istio 原生控…...

解决打印机标签尺寸匹配问题

在开发应用程序时,经常会遇到与打印机相关的各种问题,尤其是当需要打印特定尺寸的标签时。如果您正在开发一个可以打印产品标签的应用,并且遇到标签尺寸不匹配的问题,那么本文将为您提供详细的解决方案。 问题背景 假设您正在与同事开发一个可以打印产品标签的应用。您需…...

如何在A100显卡上快速部署Wan2.1图生视频API(含FastAPI配置详解)

高性能显卡实战:A100部署Wan2.1图生视频API全流程解析 当NVIDIA A100显卡遇上Wan2.1图生视频模型,会碰撞出怎样的创意火花?作为当前最先进的生成式AI视频工具之一,Wan2.1凭借其14B参数的强大模型,正在改变内容创作的工…...

Claude Code + PromptX 实战:如何让AI像你的最佳实习生一样写代码

Claude Code PromptX 实战:如何让AI像你的最佳实习生一样写代码 在软件开发领域,AI辅助编程已经从概念验证阶段迈入了实际生产力阶段。Claude Code与PromptX的组合,为开发者提供了一个强大的"虚拟实习生"——它不会抱怨加班&#…...

别再乱接纽扣电池了!STM32 VBAT引脚的正确外围电路设计(附5种常见错误分析)

STM32 VBAT电路设计避坑指南:从原理到实践的5个关键错误解析 在STM32硬件设计中,VBAT引脚的处理看似简单,却暗藏玄机。许多工程师在第一次接触这个为RTC和备份寄存器供电的引脚时,往往会陷入"接个电池就能用"的误区。事…...

Cyber Engine Tweaks:解锁《赛博朋克2077》终极模组开发能力的5大核心功能 [特殊字符]

Cyber Engine Tweaks:解锁《赛博朋克2077》终极模组开发能力的5大核心功能 🚀 【免费下载链接】CyberEngineTweaks Cyberpunk 2077 tweaks, hacks and scripting framework 项目地址: https://gitcode.com/gh_mirrors/cy/CyberEngineTweaks Cyber…...

OCS2与Pinocchio联调避坑指南:如何让机械臂MPC求解速度提升3倍?

OCS2与Pinocchio联调避坑指南:如何让机械臂MPC求解速度提升3倍? 在工业机械臂控制领域,实时模型预测控制(MPC)的求解效率直接决定了系统的响应速度与稳定性。OCS2作为ETH Zurich开发的高性能MPC求解器,结合…...

Ruoyi-Vue3实战:10分钟搞定学生管理系统CRUD(附完整SQL)

Ruoyi-Vue3学生管理系统实战:从零到部署的完整指南 在当今快速迭代的开发环境中,选择高效的技术栈至关重要。Ruoyi-Vue3作为基于Spring Boot和Vue3的企业级开发框架,以其模块化设计和丰富的功能组件,成为快速构建管理系统的首选方…...

告别手动截图!用Python脚本从ROS bag文件里精准提取带时间戳的图片(附完整代码)

告别手动截图!用Python脚本从ROS bag文件里精准提取带时间戳的图片(附完整代码) 在计算机视觉和机器人研究中,从ROS bag文件中高效提取带时间戳的图像数据是构建数据集的关键步骤。传统方法依赖ROS自带工具,但常面临提…...

旧iOS设备维护全流程解决方案:Legacy iOS Kit实用指南

旧iOS设备维护全流程解决方案:Legacy iOS Kit实用指南 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to downgrade/restore, save SHSH blobs, and jailbreak legacy iOS devices 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit Legacy…...

BinCmdParser:嵌入式二进制命令动态解析器

1. BinCmdParser:面向嵌入式通信的动态二进制命令解析器 在工业控制、传感器网络与跨平台设备互联场景中,串口/UART/SPI/I2C等低带宽物理通道常承载结构化二进制指令。传统固定帧格式(如Modbus RTU、自定义8字节头4字节长度2字节CRC&#xff…...

别再手动推导了!用Sophus库5分钟搞定机器人SLAM中的位姿插值与扰动更新

别再手动推导了!用Sophus库5分钟搞定机器人SLAM中的位姿插值与扰动更新 在机器人SLAM开发中,你是否曾为手动推导旋转矩阵的插值公式而抓狂?是否在实现位姿扰动更新时被四元数微分弄得晕头转向?今天,我们将用Sophus库彻…...

【多模态技术解析】先对齐再融合:动量蒸馏如何重塑视觉与语言表征学习

1. 为什么视觉和语言要先对齐再融合? 想象一下你正在教一个小朋友认识动物。如果先给他看一张猫的图片,再告诉他"这是狗",小朋友肯定会困惑。这就是典型的模态未对齐问题——视觉信息和语言信息没有正确匹配。在多模态AI领域&#…...

银发健康消费“新战场”:线下渠道红利期开启,10+嘉宾重磅分享实战方法论

​银发经济与连锁药店转型的双向奔赴整理 | AgeClub内容团队前言当前,中国银发经济已成为国内增长最快的赛道之一。数据显示,我国银发经济市场规模已突破 10 万亿元,未来整体规模有望超过 30 万亿元。精准对接优质渠道,成为众多银…...

Windows系统下Neo4j社区版手动安装与配置指南(非Docker方案)

1. 环境准备:JDK安装与验证 在Windows系统下手动安装Neo4j社区版,第一步就是搞定Java环境。我见过太多新手卡在这一步,其实只要注意几个关键点就能轻松过关。Neo4j作为基于Java开发的图数据库,必须依赖JDK才能运行,但不…...

ESP32/ESP8266轻量级HA MQTT自动发现C++库

1. 项目概述 HA MQTT Discovery 是一个专为嵌入式平台(特别是 ESP32/ESP8266)设计的轻量级 C 库,用于实现与 Home Assistant 的原生 MQTT 自动发现(Auto-Discovery)协议兼容的设备与实体注册。其核心目标并非替代完整…...

Arduino蓝牙TPMS解析库:7字节广告数据逆向与嵌入式解码实践

1. BluetoothTPMS 库技术解析:面向嵌入式系统的蓝牙胎压监测数据解码实践1.1 项目定位与工程价值BluetoothTPMS 是一个专为 Arduino 平台设计的轻量级开源库,核心目标是实现对低成本商用 TPMS(Tire Pressure Monitoring System)传…...