设计模式之模板方法

一、概述

定义一个操作中的算法的骨架,将一些步骤延迟到子类中。 TemplateMethod使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。

二、适用性

1.一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

2.各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。 首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。 最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

3.控制子类扩展。

三、参与者

1.AbstractClass 定义抽象的原语操作(primitive operation),具体的子类将重新定义它们以实现一个算法的各个步骤。 实现一个模板方法,定义一个算法的骨架。 该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。

2.ConcreteClass 实现原语操作以完成算法中与特定子类相关的步骤。

四、类图

五、示例

AbstractClass

public abstract class Template {public abstract void print();public void update() {System.out.println("开始打印");for (int i = 0; i < 10; i++) {print();}}
}

ConcreteClass

public class TemplateConcrete extends Template{@Overridepublic void print() {System.out.println("这是子类的实现");}
}

自测

@Test
public void testTemplate() {Template temp = new TemplateConcrete();temp.update();
}

自测结果

Connected to the target VM, address: '127.0.0.1:12824', transport: 'socket'
开始打印
这是TemplateConcrete类的实现
这是TemplateConcrete类的实现
这是TemplateConcrete类的实现
Disconnected from the target VM, address: '127.0.0.1:12824', transport: 'socket'

六、实践

封装

/*** @author lyonardo* @Description 纷享事件变更订阅处理基类:纷享事件变更返回值有书大局id,通过id查询详情;根据变更事件类型,天翎进行相应操作* @createTime 2022年09月24日 14:35:00*/
@Slf4j
public abstract class FxBaseListenerAbstract<T, E> {private final AccessTokenServcie accessTokenServcie = SpringUtil.getBean(AccessTokenServcie.class);/* private final MongoService mongoService = SpringUtil.getBean(MongoService.class);public E pick(String dataId, Class<E> var2){return mongoService.findById(dataId,var2);}*/public E pickFx(BaseObjectDataBO baseObjectDataBO, String url, Class<E> var2){String detalString = pickFxResult(baseObjectDataBO,url);return JSON.parseObject(detalString, var2);}protected abstract T getConverter(E resource);public void dataHandle(String dataObjectApiName, String dataId , String url, IService<T> iService, LambdaUpdateWrapper<T> updateWrapper, Class<E> var2){GetDetailObjectDataBO getDetailObjectDataBO = buildGetDetailObjectDataBO(dataObjectApiName, dataId);E fxObjBO = this.pickFx(getDetailObjectDataBO, url, var2);if(Objects.nonNull(fxObjBO)){T tlkObjDO = getConverter(fxObjBO);log.info("FxBaseListenerAbstract==>dataHandle getConverter对象转换结果tlkObjDO=>{}", JSON.toJSONString(tlkObjDO));if(Objects.nonNull(tlkObjDO)){iService.saveOrUpdate(tlkObjDO, updateWrapper);}else {log.warn("FxBaseListenerAbstract==>dataHandle getConverter对象转换出现异常");}}else {log.warn("FxBaseListenerAbstract==>dataHandle没有pickFx到纷享对象数据");}}public String pickFxResult(BaseObjectDataBO baseObjectDataBO, String url){Assert.notNull(accessTokenServcie,"没有获取到纷享token");//获取接口授权tokenFxiaokeAccessToken fxiaokeAccessToken = accessTokenServcie.getAccessToken();Assert.notNull(fxiaokeAccessToken,"没有获取到纷享token");//组装接口入参FxiaokeApiReqBO fxiaokeApiReqBO = FxiaokeUtil.buildInvalidOrGetParam(fxiaokeAccessToken, accessTokenServcie.getCurrentOpenUserId(), baseObjectDataBO);//入参转换jsonString jsonString = JSON.toJSONString(fxiaokeApiReqBO);log.info("数据处理同步纷享接口入参=>{}", jsonString);//调用纷享预设对象(属性对象)APIString result = OsHttpClient.create().post(url, jsonString);return FxiaokeUtil.handleResponseResult(result);}
}

使用

/*** @author lyonardo* @Description 客户监听订阅事件* @createTime 2022年09月20日 09:38:00*/
@Slf4j
@Service
public class FxAccountListener extends FxBaseListenerAbstract<TlkAccountInfoDO, FxAccountObjBO> {private final ITlkAccountInfoService service = SpringUtil.getBean(ITlkAccountInfoService.class);@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)public void handle(String eventType, String dataId) {if (EventTypeConstants.UPDATE.equals(eventType) || EventTypeConstants.INSERT.equals(eventType)) {//请求解析出参LambdaUpdateWrapper<TlkAccountInfoDO> updateWrapper = new LambdaUpdateWrapper<TlkAccountInfoDO>().eq(TlkAccountInfoDO::getItemThirdId, dataId);this.dataHandle(DataObjectApiNameConstants.ACCOUNTOBJ, dataId, FxCommonEnum.GET.buildUrl(), service, updateWrapper, FxAccountObjBO.class);} else if ( EventTypeConstants.INVALID.equals(eventType) || EventTypeConstants.DELETE.equals(eventType)) {service.remove(new LambdaQueryWrapper<TlkAccountInfoDO>().eq(TlkAccountInfoDO::getItemThirdId, dataId));} else {throw new OsRuntimeException(FailCodeEnum.FAIL);}}@Overrideprotected TlkAccountInfoDO getConverter(FxAccountObjBO resource) {TlkAccountInfoDO tlkAccountInfoDO = TlkAccountInfoDOConverter.INSTANCE.fxAccountObjBo2Do(resource);String mark = CustomerLevelEnum.getMarkByCode(tlkAccountInfoDO.getItemCustomerLevelCode());if(StringUtils.isNotEmpty(mark)){tlkAccountInfoDO.setItemCustomerLevelName(mark);}else if("".equals(mark)){tlkAccountInfoDO.setItemCustomerLevelCode(CustomerLevelEnum.MSTSC.getCode());tlkAccountInfoDO.setItemCustomerLevelName(CustomerLevelEnum.MSTSC.getDescription());}else {tlkAccountInfoDO.setItemCustomerLevelCode("cooperation_price");tlkAccountInfoDO.setItemCustomerLevelName("项目合作价");}return tlkAccountInfoDO;}
}

通过对核心方法的抽取处理以及公共抽象方法的封装,使用工厂模式、单例模式、模板方法等,让团队其他开发在进行几十上百个业务对象进行全量、增量、对接开发时,只需要关注和实现业务对象的handle方法和对象转换处理getConverter,不用关注具体的细节,不仅大大减少了代码重复量和工作量,也大大降低了易错率。

PS:在实际工作过程中,中高级同事不仅询问Java不是单继承吗?耐心解说abstract类的特点并po出Spring源码解答;帮解决属性属性值等全量增量对接问题并重写、自测。某说某在哪用到了啥啥啥设计模式,他们也说他们也用到了啥啥啥设计模式。问啥啥啥设计模式用在哪了、能把路径发某学习下吗?然后支支吾吾,这样子就比较不太好沟通。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人机交互与人机混合智能的区别

人机交互和人机融合智能是两个相关但不完全相同的概念&#xff1a; 人机交互是指人与计算机之间的信息交流和互动过程。它关注的是如何设计和实现用户友好的界面&#xff0c;以便人们能够方便、高效地与计算机进行沟通和操作。人机交互通常强调用户体验和界面设计&#xff0c;旨…

6.7.tensorRT高级(1)-使用onnxruntime进行onnx模型推理过程

目录 前言1. python-ort2. C-ort总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-使用 onnxruntime 进行 on…

[openCV]基于拟合中线的智能车巡线方案V2

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表"""newDir d…

[ MySQL ] — 库和表的操作

目录 库的操作 创建数据库 语法&#xff1a; 使用&#xff1a; 字符集和校验规则 查看系统默认字符集以及校验规则 查看数据库支持的字符集 查看数据库支持的字符集校验规则 校验规则对数据库的影响 操纵数据库 查看数据库 显示创建语句 修改数据库 删除数据库 备…

【Linux】计算机网络套接字编写

文章目录 前言TCP协议和UDP协议网络字节序socket接口sockaddr结构1.创建套接字 cs2.绑定端口号 s3.监听socket s4.接受请求 s5.建立连接 c 地址转换函数字符串转in_addrin_addr转字符串 recvfrom和sendto 前言 上篇文章我们学习了计算机网络分层&#xff0c;了解了网络通信的本…

Vue3_对响应式对象解构赋值之后失去响应性——toRefs()

官网toRefs() :响应式 API&#xff1a;工具函数 | Vue.js toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref&#xff0c;请改用 toRef。 setup(){const state reactive({name:"张三"age:14})const stateAsToRefs toRef…

保留网络:大型语言模型的Transformer继任者

原文信息 原文题目&#xff1a;《Retentive Network: A Successor to Transformer for Large Language Models》 原文引用&#xff1a;Sun Y, Dong L, Huang S, et al. Retentive Network: A Successor to Transformer for Large Language Models[J]. arXiv preprint arXiv:2…

ArduPilot开源代码之Companion Computers简单分析

ArduPilot开源代码之Companion Computers简单分析 1. 源由2. 伴机系统2.1 APSync2.2 DroneKit2.3 FlytOS2.4 Maverick2.5 ROS2.6 Rpanion-server 3. 总结4. 参考资料 1. 源由 从稳定性&#xff0c;社区群体&#xff0c;以及开源方式的角度看&#xff0c;Ardupilot是不错的选择…

Python3 处理PDF之PyMuPDF 入门

PyMuPDF 简介 PyMuPDF是一个用于处理PDF文件的Python库&#xff0c;它提供了丰富的功能来操作、分析和转换PDF文档。这个库的设计目标是提供一个简单易用的API,使得开发者能够轻松地在Python程序中实现PDF文件的各种操作。 PyMuPDF的主要特点如下&#xff1a; 跨平台兼容性&a…

Spring Data JPA源码

导读: 什么是Spring Data JPA? 要解释这个问题,我们先将Spring Data JPA拆成两个部分&#xff0c;即Sping Data和JPA。 从这两个部分来解释。 Spring Data是什么? 摘自: https://spring.io/projects/spring-data Spring Data’s mission is to provide a familiar and cons…

1、Spark SQL 概述

1、Spark SQL 概述 Spark SQL概念 Spark SQL is Apache Spark’s module for working with structured data. 它是spark中用于处理结构化数据的一个模块 Spark SQL历史 Hive是目前大数据领域&#xff0c;事实上的数据仓库标准。 Shark&#xff1a;shark底层使用spark的基于…

NOsql之MongoDB入门分享

目录 一、MongoDB简介 1、概念理解 2、yum安装部署 3、二进制安装部署 4、配置文件解析 二、MongoDB基本管理 1、登录操作 2、管理命令 3、用户管理 一、MongoDB简介 1、概念理解 关系型数据库&#xff08;RDBMS:Relational Database Management System) MySql、Ora…

oop基础--成员方法传参机制(重要)

文章目录 1. 基本数据类型的传参机制2. 引用数据类型的传参机制 1. 基本数据类型的传参机制 先让我们猜一下如下代码的输出结果~ public class MethodParameter01 {//编写一个 main 方法public static void main(String[] args) {int a 10;int b 20;//创建 A 对象 名字 obj…

计算机毕设 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两…

oracle数据库创建用户并插入数据

Oracle第一话 数据库权限设置 序言 ​ 具体的错误类型&#xff0c;我看大概是这样的 一 Oracle比mysql复杂一点 首先&#xff0c;创建一个表空间 -- 创建名为"TEST_DATA"表空间 CREATE TABLESPACE TEST_DATA NOLOGGING -- 数据存放的位置 DATAFILE D:\test_data…

Qt项目---简单的计算器

在这篇技术博客中&#xff0c;我们将介绍如何使用Qt框架实现一个简单的计算器应用。我们将使用C编程语言和Qt的图形用户界面库来开发这个应用&#xff0c;并展示如何实现基本的算术操作。 项目设置 首先&#xff0c;我们需要在Qt Creator中创建一个新的Qt Widgets应用程序项目…

【二进制安全】堆漏洞:Double Free原理

参考&#xff1a;https://www.anquanke.com/post/id/241598 次要参考&#xff1a;https://xz.aliyun.com/t/6342 malloc_chunk 的源码如下&#xff1a; struct malloc_chunk { INTERNAL_SIZE_T prev_size; /*前一个chunk的大小*/ INTERNAL_SIZE_T size; /*当前chunk的…

TPlink DDNS 内网穿透?外网访问设置方法

有很多小伙伴都想知道&#xff1a;TPlink路由器怎么设置DDNS内网穿透&#xff1f;今天&#xff0c;小编就给大家分享一下TPlink DDNS 外网访问设置方法&#xff0c;下面是图文教程&#xff0c;帮助新手快速入门DDNS设置。 本文介绍的是云路由器TP-LINK DDNS的设置方法。TP-LIN…

Keil软件添加STC数据包方法

添加数据包方法如下&#xff1a; &#xff08;1&#xff09;首先&#xff0c;打开STC-ISP烧录工具&#xff1b; &#xff08;2&#xff09;点击“Keil仿真设置”&#xff0c;然后点击“添加型号和头文件到Keil中&#xff0c;添加STC仿真器驱动到Keil中”。 &#xff08;3&…

60多行代码仿制B站首页一个好看的卡片效果

文章目录 1、为啥是这个&#xff1f;2、仿制效果3、实现思路4、代码5、查看B站如何实现 1、为啥是这个&#xff1f; 看到Bilibili首页的一个卡片&#xff0c;看着效果很不错&#xff0c;给人很舒适的感觉。一琢磨貌似也不难&#xff0c;甚至只需要一层 div 就可以实现主要框架…