设计模式之模板方法

一、概述

定义一个操作中的算法的骨架,将一些步骤延迟到子类中。 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* @createTime 2022年09月20日 13:52:00*/@Slf4j
public abstract class FxBaseExtServiceAbstract<T, E> {private final AccessTokenServcie accessTokenServcie = SpringUtil.getBean(AccessTokenServcie.class);/* private final MongoService mongoService = SpringUtil.getBean(MongoService.class);public List<E> pick(Class<E> var2) {return mongoService.find(new Query(), var2);}*/public List<E> pickFx(String dataObjectApiName, List<Filter> filterList, String url, Class<E> var2) {Assert.notNull(accessTokenServcie,"没有获取到纷享token");//获取接口授权tokenFxiaokeAccessToken fxiaokeAccessToken = accessTokenServcie.getAccessToken();Assert.notNull(fxiaokeAccessToken,"没有获取到纷享token");List<E> all = new ArrayList<>();long startTime = System.currentTimeMillis();String dataId = "";for (; ; ) {List<Filter> filters = new ArrayList<>(filterList);filters.add(new Filter("_id", Lists.newArrayList(dataId), "GT"));List<Order> orderList = new ArrayList<>();orderList.add(new Order("_id", true));//组装接口入参FxiaokeBaseReq map = FxiaokeUtil.buildParamMapExt(dataObjectApiName, null, filters, orderList, fxiaokeAccessToken, accessTokenServcie.getCurrentOpenUserId());//入参转换jsonString jsonString = JSON.toJSONString(map);log.info("数据处理同步纷享接口入参=>{}", jsonString);//调用纷享预设对象(属性对象)APIString result = OsHttpClient.create().post(url, jsonString);String dataListString = FxiaokeUtil.handleResponseResult(result);if (!StringUtils.hasText(dataListString)) {break;}JSONArray isExit = JSON.parseArray(dataListString);if (isExit.isEmpty()) {break;}JSONObject jsonObject = JSONObject.parseObject(isExit.get(isExit.size() - 1).toString());if (jsonObject.isEmpty()) {break;}if (all.size()> 2000) {break;}dataId = jsonObject.getString("_id");log.info("dataId=>>>{}", dataId);all.addAll(JSON.parseArray(dataListString, var2));}long endTime = System.currentTimeMillis();long totalTime = (endTime - startTime) / 1000;log.info("请求接口全量数据耗时=>>>{}秒", totalTime);return all;}/*** @param resourceList 源list* @description list转换器 List<E> -> List<T>* @datetime 2022-09-20 16:31:04*/protected abstract List<T> getListConverter(List<E> resourceList);public void handle(List<T> list, IService<T> iService) {long start = System.currentTimeMillis();iService.remove(new QueryWrapper<T>().eq("ITEM_DATA_FROM", DataFromEnum.FXIAOKE.getCode()));iService.saveOrUpdateBatch(list);long end = System.currentTimeMillis();log.info("全量数据处理同步耗时:=>{}秒", (end - start)/ 1000);}public void incrHandle(List<T> list, IService<T> iService) {long start = System.currentTimeMillis();iService.saveOrUpdateBatch(list);long end = System.currentTimeMillis();log.info("增量据处理同步耗时:=>{}", (end - start));}/*** @param type     1  天翎业务表id是纷享的;2 天翎业务表id是天翎的* @param dataId* @param list* @param iService* @description* @datetime 2022-09-22 20:50:44*/public void incrHandlePlus(Integer type, String dataId, Wrapper<T> queryWrapper, List<T> list, IService<T> iService) {long start = System.currentTimeMillis();if (1 == type) {iService.removeById(dataId);} else {iService.remove(queryWrapper);}iService.saveOrUpdateBatch(list);long end = System.currentTimeMillis();log.info("增量数据处理同步耗时:=>{}秒", (end - start) / 1000);}public void dataHandle(String dataObjectApiName, Integer type, List<Filter> filterList, String dataId,String url, Wrapper<T> queryWrapper, IService<T> iService, Class<E> var2) {if (CollectionUtils.isEmpty(filterList) && !StringUtils.hasText(dataId)) {filterList = Arrays.asList(new Filter("is_deleted", Collections.singletonList(Boolean.FALSE), "EQ"),new Filter("life_status", Collections.singletonList("normal"), "EQ"));}if (StringUtils.hasText(dataId)) {filterList.add(new Filter("_id", Lists.newArrayList(dataId), "EQ"));}//请求解析出参List<E> resourceList = this.pickFx(dataObjectApiName, filterList, url, var2);//打印一条数据log.info("list size ==> {}\n,   resourceList ==>\n {}", resourceList.size(), JSON.toJSONString(Optional.of(resourceList).map(t -> t.get(0)).orElse((E) "")));if (StringUtils.hasText(dataId)) {this.incrHandlePlus(type, dataId, queryWrapper, getListConverter(resourceList), iService);} else {this.handle(getListConverter(resourceList), iService);this.getListConverterFinall(resourceList);}}protected abstract void getListConverterFinall(List<E> resourceList);}

使用

/*** @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,不用关注具体的细节,不仅大大减少了代码重复量和工作量,也大大降低了易错率。

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

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

相关文章

无涯教程-Perl - Subroutines(子例程)

定义子程序 Perl编程语言中 Subroutine子程序定义的一般形式如下: sub subroutine_name {body of the subroutine } 调用该Perl Subroutine的典型方式如下- subroutine_name( list of arguments ); 在Perl 5.0之前的版本中&#xff0c;调用 Subroutine的语法略有不同&…

@ControllerAdvice注解使用及原理探究 | 京东物流技术团队

最近在新项目的开发过程中&#xff0c;遇到了个问题&#xff0c;需要将一些异常的业务流程返回给前端&#xff0c;需要提供给前端不同的响应码&#xff0c;前端再在次基础上做提示语言的国际化适配。这些异常流程涉及业务层和控制层的各个地方&#xff0c;如果每个地方都写一些…

STM32入门学习之定时器中断

1.STM32的通用定时器是可编程预分频驱动的16位自动装载计数器。 STM32 的通用定时器可以被用于&#xff1a;测量输入信号的脉冲长度 ( 输入捕获 ) 或者产生输出波 形 ( 输出比较和 PWM) 等。 使用定时器预分频器和 RCC 时钟控制器预分频器&#xff0c;脉冲长度和波形 周…

如何下载和编译 Android 源码?

本文为洛奇看世界(guyongqiangx)原创&#xff0c;转载请注明出处。 文章链接&#xff1a;https://blog.csdn.net/guyongqiangx/article/details/132125431 网上关于如何下载 Android 源码和编译的文章很多&#xff0c;其中最常见的就是 Android 官方文档&#xff1a; 下载源代码…

socker套接字

1.打印错误信息 2.socketaddr_in结构体 结构体&#xff1a; &#xff08;部分库代码&#xff09; (宏中的##) 3.manual TCP: SOCK_STREAM &#xff1a; 提供有序地&#xff0c;可靠的&#xff0c;全双工的&#xff0c;基于连接的流式服务 UDP: 面向数据报

list交并补差集合

list交并补差集合 工具类依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.8.1</version> </dependency><dependency><groupId>commons-collections&…

刷题笔记 day7

力扣 209 长度最小的子数组 解法&#xff1a;滑动指针&#xff08;对同向双指针区间内的数据处理&#xff09; 1&#xff09;先初始化 两个指针 left &#xff0c;right。 2&#xff09;右移指针right的同时使用sum记录指针right处的值&#xff0c;并判断sum的值是否满足要求&…

uniapp封装request请求

在基础文件里面创建一个api文件 在创建两个 js文件 http.js 里面封装 request 请求 let baseUrl https://white.51.toponet.cn; //基地址 export const request (options {}) > {//异步封装接口&#xff0c;使用Promise处理异步请求return new Promise((resolve, reject…

IDEA基础使用

IDEA基础使用 1、IDEA中显示用法和用户截图展示有调用显示无调用显示 对应方法 2、如何找出项目中所有不被调用方法截图展示对应方法 3、常用代码(Code)说明及快捷键:4、未完待续待日后更新。。。总结&#xff1a;欢迎指导&#xff0c;也祝码友们代码越来越棒&#xff0c;技术越…

解密爬虫ip是如何被识别屏蔽的

在当今信息化的时代&#xff0c;网络爬虫已经成为许多企业、学术机构和个人不可或缺的工具。然而&#xff0c;随着网站安全防护的升级&#xff0c;爬虫ip往往容易被识别并屏蔽&#xff0c;给爬虫工作增加了许多困扰。在这里&#xff0c;作为一家专业的爬虫ip供应商&#xff0c;…

【ARM Coresight 系列文章 2.5 - Coresight 寄存器:PIDR0-PIDR7,CIDR0-CIDR3 介绍】

文章目录 1.1 JEDEC 与 JEP1061.2 PIDR0-PIDR7(peripheral identification registers)1.2 CIDR0-CIDR3(Component Identification Registers) 1.1 JEDEC 与 JEP106 JEDEC和JEP106都是来自美国电子工业联合会&#xff08;JEDEC&#xff0c;Joint Electron Device Engineering C…

【李宏毅机器学习·学习笔记】Tips for Training: Adaptive Learning Rate

本节课主要介绍了Adaptive Learning Rate的基本思想和方法。通过使用Adaptive Learning Rate的策略&#xff0c;在训练深度神经网络时程序能实现在不同参数、不同iteration中&#xff0c;学习率不同。 本节课涉及到的算法或策略有&#xff1a;Adgrad、RMSProp、Adam、Learning …