最新要闻
- 【播资讯】高温之下 导游及游客安全更要上心
- 大模型中的“罗翔” 北大团队发布法律大模型ChatLaw-天天快资讯
- 日本核污染水排海符合标准!合法性不受认可:日本被爆贿赂IAEA百万欧元 天天快资讯
- 【当前热闻】女子推开保护罩让孩子摸文物 管理方:禁止触摸
- RTX 4060遇冷:没想到降价这么快、这么狠! 全球讯息
- 东风雪铁龙公司回应C6拖欠补贴:8月15日前全部退还
- 国家气候中心:今年盛夏极端天气气候事件偏多 高温、强降水等来袭_世界资讯
- 实时焦点:AMD锐龙5 7500F真身浮现:Zen4第一次没了核显、价格诱人
- 男子被鱼刺扎伤截掉中指:感染病死率高的创伤弧菌 医生提醒
- 每日看点!高温叠加少雨:北方2地出现特旱
- 【天天速看料】32:9比例曲面屏!红魔公布49英寸QD-OLED电竞显示器
- 要闻速递:42万买奥迪A7L新车 先异响后地库抛锚!第一视角感受车主无奈
- 今日看点:华建集团下属公司水利院联合签署有关防洪能力提升工程合同
- 腾势N7做了违背王传福的决定!比亚迪首款智能车30万开卖
- 每日简讯:极摩客新一代迷你主机要上14代酷睿 GPU追赶RTX 3050
- 理想联合创始人沈亚楠退出公司股东行列:李想持股比例超95%
手机
光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
- 搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 视点!美国首位女总统即将诞生?拜登恐怕要提前下岗,美政坛迎来变局?
- 当前速递!用理想仪器实现更好的颗粒 德国新帕泰克亮相CPHI & PMEC China获好评
- 微粒贷怎么申请开通 开通方法如下
- 焦点简讯:心疼!这位40岁的云南缉毒警,已是满头白发
家电
每日消息!java基础之行为抽象
我在开发热部署的项目过程中,遇到了以下的情况:
(相关资料图)
有好几个热部署的场景,比如说:
- java类热部署(场景A)
- mybatis的xml热部署(场景B)
- 属性配置文件热部署(场景C)
然后这些场景大致有两种热部署的操作,那就是:
- 操作a:新增与修改;
- 操作b:回退,
而所有的场景的所有操作,处理的文件是一个列表,处理的场景需要根据文件后缀自己区分,每个文件的处理不管成功失败都要记录日志。
这是基本的场景。刚开始的写法极为不内聚:
1、写两个操作处理类,用来处理新增修改和回滚操作
2、每个场景分别写一个处理器,每个处理器写两个主要方法分别处理两个操作:publish(), rollback();
3、每个操作处理类先将两个文件列表根据进行分类,分别区分出三个场景的文件列表,分别调用对应处理器的操作方法
4、由于每个操作都需要记录日志,分失败成功两个情况,那就要在3中提到6个操作方法中对这两种情况进行日志记录。
我们来看一下上面写法的特点:
步骤1 涉及2个类,每个类3个判断
步骤2涉及3个场景类6个场景方法
步骤3涉及2个操作类6个操作方法
步骤4涉及12个类似的处理
以上的方案不能说错误,但是是一种充满不合理的正确。
我们来分析一下,能够如何更好的进行抽象,让我们的代码看起来更加的优雅。
我们经常对我们开发过程中碰到过的实体类进行抽象,详细大家并不陌生。比如对一下公共的属性进行抽象,但自从jdk8发布以来,方法也称为了“一等公民”, 跟我们的数据类型都拥有相同的地位了,我们要适应对行为动作进行抽象。
对函数式接口还不熟悉的小伙伴,可以移步另外一篇文章先做了解:lamda表达式与函数式接口
抽象一般是对共性的部分进行提取。
那我们可以看到,上面提到的共性部分有:
- 每个处理器都有新增修改和回滚两个处理场景;
- 每个操作,不管成功失败都要记录日志;
首先,针对第一点:每个场景都有publish(), rollback()两个方法,我们可以考虑抽出一个接口,
public interface IHotSwapHandler { /** * 新增修改 */ boolean publish (List fileList, String transId); /** * 回退 */ boolean publish (List fileList, String transId);}
然后每个场景作不同的实现。
那针对第二点,我们要尝试将这12个try-catch然后记录日志的动作整合成一个,因为这12个处理的不同,其实只是try里面的部分。我们可以把这12个处理简化成下面的步骤:
for (FileInfo fileinfo : fileList) {try {// 新增修改/回滚 操作}catch (Throwable e) {// 记录日志}}
可以看到,距离最后的“殊途同归“,还差新增修改/回滚 操作的抽象,而遍历的动作,是每一个场景每个处理都要做。针对这种所有实现类的所有方法都要做步骤,我们考虑在抽象实现类中实现,相当于众多实现类大家长,把各自场景都需要做的给处理了,让没个场景实现类的实现更加纯粹
那我们先实现一个抽象类
public abstract class HotSwapHandler implements IHotSwapHandler { @Override public boolean commit(List fileList, String transId) { return hotswap(fileList, transId); } @Override public boolean rollback(List fileList, String transId) { return hotswap(fileList, transId); } /** * 遍历逻辑 **/ protected boolean hotswap(List fileList, String transId) { boolean success = true; if (CollectionUtils.isEmpty(fileList) || Objects.isNull(logFunction)) { return success; } for (FileInfo fileInfo : fileList) { boolean result = 【新增修改\回退操作】 if (!result) { success = result; // 失败后中断发布 break; } } return success; } }
如此一来,抽象类实现的新增修改\回退操作都已经走了相同的遍历逻辑了,最后各自的具体实现逻辑了。抽象实现类只做了他力所能及的事情,帮你们把遍历逻辑统一了起来,就是上面简单模型中的
for (FileInfo fileinfo : fileList) {}
但新增修改\回退操作需要正式各自实现类去实现,
try {// 新增修改/回滚 操作}catch (Throwable e) {// 记录日志}
但细心的同学会发现,新增修改/回滚 操作是两个不同的操作呀,按正常的写法我要在 protected boolean hotswap(List
public interface IHotSwapHandler { /** * 新增修改 * * @param fileList 文件列表 * @param transId 流水 * @param hotswapType 类型 * @return */ boolean publish (List fileList, String transId, HotswapTypeEnum hotswapType); /** * 回退 * * @param fileList 文件列表 * @param transId 流水 * @param hotswapType 类型 * @return */ boolean publish (List fileList, String transId, HotswapTypeEnum hotswapType);}
抽象实现类应该是:
public abstract class AbstractHotSwapHandler implements IHotSwapHandler { @Override public boolean commit(List fileList, String transId, HotswapTypeEnum.PUBLISH) { return hotswap(fileList, transId); } @Override public boolean rollback(List fileList, String transId, HotswapTypeEnum.ROLLBACK) { return hotswap(fileList, transId); } /** * 遍历逻辑 **/ protected boolean hotswap(List fileList, String transId, HotswapTypeEnum hotswapType) { boolean success = true; if (CollectionUtils.isEmpty(fileList) || Objects.isNull(logFunction)) { return success; } for (FileInfo fileInfo : fileList) { if(hotswapType == HotswapTypeEnum.PUBLISH) { realPublish(fileInfo, transId); } if(hotswapType == HotswapTypeEnum.ROLLBACK) { realRollback(fileInfo, transId); } boolean result = 【新增修改\回退操作】 if (!result) { success = result; // 失败后中断发布 break; } } return success; } protected abstract boolean realPublish(FileInfo fileInfo, String transId); protected abstract boolean realRollback(FileInfo fileInfo, String transId); }
然后每个实现类继承AbstractHotSwapHandler,然后本质是实现抽象实现类的两个方法
protected abstract boolean realPublish(FileInfo fileInfo);protected abstract boolean realRollback(FileInfo fileInfo);
这样似乎很完美了,但你会发现,其实我们要解决的第二点还没有解决,因为当你去写实现类的时候,还是会发现,你每个实现类的realPublish和realRollback都需要写一下的逻辑
try {// 操作}catch (Throwable e) {// 记录日志}
操作操作,当我们把两种类型的操作都看成是一个行为的时候,我们就知道改如何去抽象出这一层了,此时我们的新晋“一等公民”就得登场了:FunctionInterface,它允许你将一个动作作为参数传入来。然后直接调用他的处理方法就行了。所以,我们需要一个能把新增修改/回滚看成同一个类型的类,传入尽量,我们就可以将上面的try-catch做公共处理了。所以既然是同一个类型,我们就不用标识来判断了,接口可以改回去
public interface IHotSwapHandler { /** * 新增修改 */ boolean publish (List fileList, String transId); /** * 回退 */ boolean publish (List fileList, String transId);}
新增一个FunctionInterface:LogFunction,用来处理日志记录
@FunctionalInterfacepublic interface LogFunction { default boolean apply(FileInfo fileInfo, String transId) { boolean success = true; if (Objects.isNull(fileInfo)) { return success; } try { doApply(fileInfo); HotSwapHelper.saveHotswapSuccLog(transId, fileInfo.getFileId()); } catch (Throwable e) { // 日志记录 HotSwapHelper.saveHotswapErrorLog(transId, fileInfo.getFileId()); success = false; } return success; } /** * 处理单个文件,兼容发布与回滚 * @param fileInfo 单个文件信息 * @throws Throwable */ void doApply(CommandItemFile commandItemFile) throws Throwable;}
相当于实现类其实只需要去实现void doApply(CommandItemFile commandItemFile) throws Throwable;这个方法,而由于FunctionInterface的特殊性,他能够被看成一个特殊的数据类型,而不用再新增类去实现这个接口。
依次而抽象实现类去除标识判断,
public abstract class AbstractHotSwapHandler implements IHotSwapHandler { @Override public boolean commit(List fileList, String transId, LogFunction logFunction) { return hotswap(fileList, transId, logFunction); } @Override public boolean rollback(List fileList, String transId, LogFunction logFunction) { return hotswap(fileList, transId, logFunction); } /** * 遍历逻辑 **/ protected boolean hotswap(List fileList, String transId, LogFunction logFunction) { boolean success = true; if (CollectionUtils.isEmpty(fileList) || Objects.isNull(logFunction)) { return success; } for (FileInfo fileInfo : fileList) { boolean result = logFunction.apply(fileInfo); if (!result) { success = result; // 失败后中断发布 break; } } return success; } protected abstract LogFunction realPublish(); protected abstract LogFunction realRollback(); }
因此你会看到,新增修改和回退两个操作,其实都是被看成一个行为,只是这个行为的内容不一样样,就想我们一个普通的Inger类型,它们都是整数,但可能数值是不一样的。FunctionInterface同样的道理,所有的FunctionInterface都可以说是对行为的抽象,也就是对方法的抽象,然后可以对这些方法做共性的处理,因此对FunctionInterface的定义其实很简单,只要是要对不同的行为做相同的处理,都可以定义为FunctionInterface。你也可以简单的理解,FunctionInterface的作用就是,请你告诉我一段处理逻辑,我要拿着这段处理逻辑去用,其他事情我帮你做了,你不用操心。是不是很玄幻,又那么招人喜欢。
你感受到FunctionInterface的魅力了吗
关键词:
每日消息!java基础之行为抽象
天天热资讯!华为云河图KooMap 共筑数字孪生底座 共建产业标杆
环球看热讯:商品日报(7月4日):纸浆刷新逾两个月新高 双焦走弱焦煤跌近3%
【播资讯】高温之下 导游及游客安全更要上心
大模型中的“罗翔” 北大团队发布法律大模型ChatLaw-天天快资讯
日本核污染水排海符合标准!合法性不受认可:日本被爆贿赂IAEA百万欧元 天天快资讯
【当前热闻】女子推开保护罩让孩子摸文物 管理方:禁止触摸
RTX 4060遇冷:没想到降价这么快、这么狠! 全球讯息
东风雪铁龙公司回应C6拖欠补贴:8月15日前全部退还
全球热推荐:文档在线预览 总结篇
Nftables栈溢出漏洞(CVE-2022-1015)复现
HawkEye产品深受市场认可,与多家行业龙头企业达成合作,共同开拓行业市场
国家气候中心:今年盛夏极端天气气候事件偏多 高温、强降水等来袭_世界资讯
实时焦点:AMD锐龙5 7500F真身浮现:Zen4第一次没了核显、价格诱人
男子被鱼刺扎伤截掉中指:感染病死率高的创伤弧菌 医生提醒
每日看点!高温叠加少雨:北方2地出现特旱
【天天速看料】32:9比例曲面屏!红魔公布49英寸QD-OLED电竞显示器
要闻速递:42万买奥迪A7L新车 先异响后地库抛锚!第一视角感受车主无奈
当前焦点!易基因: RRBS揭示基于DNA甲基化驱动基因的肾透明细胞癌预后模型的鉴定和验证|项目文章
每日热讯!数据万象AVIF图片压缩 - 小程序省流量利器
环球快资讯:从0开始,手写MySQL数据管理器DM
Python中对open读取文件内容时的mode模式解析
收评:A股三大股指窄幅震荡 汽车产业链股全天走强 当前视点
今日看点:华建集团下属公司水利院联合签署有关防洪能力提升工程合同
腾势N7做了违背王传福的决定!比亚迪首款智能车30万开卖
每日简讯:极摩客新一代迷你主机要上14代酷睿 GPU追赶RTX 3050
理想联合创始人沈亚楠退出公司股东行列:李想持股比例超95%
【当前热闻】董明珠谈预制菜:要让世界爱上中国味道
北科大用“卡脖子”技术做录取通知书!这种钢打破国外垄断
金丝兔压脚厂家(金丝兔)
ChatGPT 让人们大吃一惊——以下三项技术可能会带来改变
北斗卫星时钟同步服务器(卫星授时服务)天线安装意见-每日热门
每日消息!债券通助力国家金融市场对外开放稳步推进
国家气候中心:预计今年盛夏我国气候状况为一般到偏差 极端天气气候事件偏多 独家焦点
入汛以来189条河流发生超警以上洪水
小米又对华为提专利无效宣告请求 细节揭秘:涉及拍照、4G/LTE技术
不讲武德!扎克伯格偷家马斯克:推特大乱Meta趁机火速上线竞品 热资讯
天天观察:意大利原装进口:100%橙汁9.7元/L抄底0脂肪
网友称看电影《消失的她》时发现靠背有针:影院连道歉都没有
076期书生大乐透预测奖号:区间比012路比分析 天天热闻
哪里需要写哪里,FromServices注入 — ASP.NET CORE
《太极张三丰》观后感
海尔洗衣机宣传抗菌率大于99%被罚3万_时快讯
每日快看:小孩影厅排泄致退票家长拒赔偿 年纪小不懂事:网友热议为啥要带出来
滚动:镓锗出口管制!概念股应声大涨,业内:半导体产业或受影响
动车售卖盒饭出现双层价签 12306:15元卖成35元违规|全球简讯
RTX 4090 Ti四插槽巨型散热器流出:有人要价888888元
中青报谈文字失语症:别让垃圾短视频废了可思化 网友有话说 每日消息
男子偷住无人别墅多日喝光6瓶茅台:家政打扫卫生时才发现
威马汽车:公司近期开始还债复产 CEO沈晖限消令已撤销
柏拉图中的累计百分比怎么算出来的_百分比怎么算出来的
kernel pwn入门
当前要闻:柏瑞投资:亚洲高收益债券最具吸引力
高考中文题简单!老师称在越南学好中文工资更高:当地人不加班不为钱放弃生活
每日速看!199元起 雷柏VT9 PRO无线鼠标上架:68g轻量化设计
大梁+四驱!新一代哈弗H5回归:长城史上最大SUV_世界独家
全球观速讯丨谨防上当!女子网上找补漏报价800上门变4300:已有多人被骗
全球观速讯丨不到半价:八喜自选口味冰淇淋15大杯90g狂促99元
漫威系列电影观影顺序_威漫电影观影顺序
世界信息:linux Nginx+Tomcat负载均衡、动静分离
世界今亮点!CakePHP教程_编程入门自学教程_菜鸟教程-免费教程分享
js的中的函数(一)
语音房源码搭建技术分享之降噪功能详解
C#.NET Framework 使用BC库(BouncyCastle) RSA 私钥签名 公钥验签(验证签名) ver:20230704 每日观察
香港特区政府财政司司长陈茂波:进一步强化香港作为全球离岸人民币业务枢纽和国际风险管理中心的地位-看热讯
环球新动态:可转债市场首个退市整理期敲定 市场风格分化明显
天天快资讯丨普里戈任再次发声寻求支持:“你们会看到我们在前线取得新的胜利”
新能源硬派越野!比亚迪方程豹首款车型定名:叫“豹5”
天天快播:男子用共享电动车拦婚车要钱 司机曝内幕:专业闹喜人 不要红包只要100块
前有阿维塔 后有深蓝 “亲儿子”启源如何突围?-最新
荣耀全家桶来袭:手表、平板、电视全都有 焦点热门
环球消息!终于透明了!广州新规:网约车驾驶员端需显示抽成比例
每日热闻!昀冢科技:7月3日融资买入200.78万元,融资融券余额4987.8万元
B站内测搜索AI助手:输入“?”即可体验!
【笔试实战】LeetCode题单刷题-编程基础 0 到 1【二】 全球观天下
环球报道:Linux调优+Tomcat调优,超级干货,一定珍藏
三步搞定CentOS7下的MariaDB 10_天天观天下
前沿资讯!vue通用的增删改查按钮组件
制氧设备相关内容简介介绍图片_制氧设备相关内容简介介绍
广汽埃安副总经理:让特斯拉跑网约车 可能3个月车就不行了
百度专为学习打造!小度青禾学习手机第二款入网:支持5G
广汽“奇葩” 埃安凶猛_当前滚动
资讯:浙江仙居太阳像戴了美瞳:绝美彩色光晕 专家科普为何形成
当前观点:苹果Apple Beta短暂维护:iOS 17公测版要来了
亚太实业7月4日开盘涨停
spring启动流程 (3) BeanDefinition详解 每日播报
【天天报资讯】前端Vue自定义精美宫格菜单按钮组件 可设置一行展示个数 可设置成九宫格 十二宫格 十五宫格
景区放“丑女”雕塑被指侮辱女性,官方回应
微信支付每月免费提现额度引热议:1.2万免费提你会用吗?
要大涨价还买吗?iPhone 15系列新配色曝光:新渲染图亮相
复旦教授谈为何中国出不了马斯克 要对失败和试错足够包容:网友吐槽
新型进网许可标志启用 你买的手机是正品吗?最新查询方法来了_全球观察
每日聚焦:药品说明书“看不清”“看不懂”? 国家药监局进行适老化改革
自学Python之路-django模板--jinja2模板引擎配置
行政处罚的种类有哪些?行政处罚记录如何申请消除?
高考满分是多少分?高考满分状元750有几个人?
夏天是几月到几月?夏天冰箱调到几档最合适?
今日精选:多家国有大行下调美元存款利率 专家称美元存款主要面临汇兑风险
环球热文:国际金融市场早知道:7月4日
【天天热闻】武夷山属于福建还是江西 ?武夷山又增一张世界级名片