场景

同在互联网打工的小伙伴们肯定都面临这样一种场景:

通用逻辑(被多处调用)我们通常会封装成一个方法,那这个方法入参正常来说都不会少,(在开发规范中,经常会看到一条"方法入参正常不超过3个”。)面对入参超过3个的方法我们正常都会封装成一个bo类(这样扩展方法入参,再也不怕被领导diss了)。

如下图,假设现在有三个逻辑需要去调用这个方法,我们是不是都需要去build入参呀,这也是很多小伙伴会选择的调用方式。

大家都知道,在咱们这个行业最不缺的就是挑刺儿的人,这些人经常也被称为有工匠精神的码农哈哈哈!!!

那么就有工匠精神的码农看不惯红框内的代码的(怎么看都是重复代码),每次调用方法都去build入参,太麻烦了!!!

连调用方法都嫌传参麻烦,难道这就是有工匠精神的码农?

不能理解!!!

不过倒也挺好奇究竟是怎么做到自动构造参数的,所以也就有了本篇文章。

优化

现在我们假设上面提到的那个方法是一个订单价格的方法,其实这是我最近遇到的一个真实业务场景:

这里我们只需要了解影响订单价格的因素有订单明细单价、工艺单价、价格类型、订单明细长宽高,以及对应明细下单数量。面对这么多参数,而且这个方法很多地方用到,每个地方去构建参数确实是比较麻烦。

那怎么去做到自动构建入参呢,接下来就是文章的重点了。

我们首先要思考一个问题,这些参数的源头是哪里呢?

(1)可能是下单时候前端传过来的参数。(controller层用XXXDTO接收)

(2)也可能是修改某个订单明细导致订单价格须重新计算,那这个时候需要从数据库查询该订单其他订单明细重新计算,这个时候我们定义XXXPOJO类接收查询结果。(这个为啥不是entity呢,因为这些参数来自不同的实体类)

这里扯多了,不理解上面场景的小伙伴,可以理解成入参来自不同的类。

2. 参数来自不同的类,而这个方法又得去兼容这多个类。

面对这样的场景我们不禁联想到万能数据线。Type-C接口、苹果接口、安卓接口共同连接着USB接口,USB接口才是连接电源的入口。至于这三种接口怎么和USB连接才可以工作就是线内部要做事情了,外部只要关心不同类型手机对应不同的接口就可以了。
大家仔细品一下上面这个我们再常见不过的例子,我觉得太能类比到我们这个场景了。
(1) Type-C接口、苹果接口、安卓接口 --> 想调用方法的不同类(不同数据来源)
(2) USB接口 --> 方法入参
(3) 电源 --> 方法主体

也就是说我们要让这多个类与入参产生关联才可以无缝调用方法主体。

3. 我们不妨把方法的入参定义成一个接口Adapter形式(接口定义各个我们上面说的决定订单价格因素的获取方法),那么这样不同类(数据来源)就可以去实现这个接口,必定重写方法,这就相当于把构建入参的操作移到dto去做。

上面可能说的太抽象了,所以给大家再上个图,看一下具体结构

光说光看,还不如来个实操理解快呢,早知道会这么想,接下来,上代码!!!

(1)方法入参

/*** 方法入参*/
public interface OrderAmountCalAdapter {/*** 单价 单位:分*/BigDecimal obtainPrice();/*** 工艺单价 单位:分*/BigDecimal obtainCraftPrice();/*** 价格类型 2平方价格 3立方价格*/Integer obtainPriceType();/*** 长度 单位:毫米 mm*/Integer obtainLength();/*** 宽度 单位:毫米 mm*/Integer obtainWidth();/*** 厚度 单位:毫米 mm*/Integer obtainHeight();
}

(2)主方法

/*** 计算方法*/
public long calculate(OrderAmountCalAdapter adapter, Integer qty) {if (adapter == null) {throw new ApiException("计算订单金额时载体对象不能为空");}if (adapter.obtainPrice() == null) {throw new ApiException("计算订单金额时金额不能为空");}if (adapter.obtainPriceType() == null) {throw new ApiException("计算订单金额时价格类型不能为空");}if (adapter.obtainLength() == null || adapter.obtainWidth() == null || adapter.obtainHeight() == null) {throw new ApiException("计算订单金额时商品属性信息不能为空");}if (qty == null) {throw new ApiException("计算订单金额时数量不能为空");}return doCalculate(adapter, qty).longValue();
}

(3)不同DTO类(不同数据源)

/*** 不同DTO类,通过实现OrderAmountCalAdapter接口,重写方法获取DTO属性值,也就是上面说的把构建入参移到具体的DTO类来做*/
@Data
public class OrderProductProperty implements OrderAmountCalAdapter {@ApiModelProperty(value = "明细ID")private Long id;@ApiModelProperty(value = "明细单价")private Long price;@ApiModelProperty(value = "下单数量")private Integer orderQuantity;@ApiModelProperty(value = "工艺单价")private Long craftPrice;@ApiModelProperty(value = "长度(单位mm)")private Integer length;@ApiModelProperty(value = "宽度(单位mm)")private Integer width;@ApiModelProperty(value = "高度(单位mm)")private Integer height;@ApiModelProperty("价格类型 2平方 3立方")private Integer priceType;@Overridepublic BigDecimal obtainPrice() {return BigDecimal.valueOf(getPrice() == null ? 0L : getPrice());}@Overridepublic BigDecimal obtainCraftPrice() {return BigDecimal.valueOf(getCraftPrice() == null ? 0L : getCraftPrice());}@Overridepublic Integer obtainPriceType() {return getPriceType();}@Overridepublic Integer obtainLength() {return getLength();}@Overridepublic Integer obtainWidth() {return getWidth();}@Overridepublic Integer obtainHeight() {return getHeight();}}

这就达到我们上面所说的不用构建方法的入参就可以调用方法了,是不是很精妙哈哈哈。

其实仔细想一想,这不就是适配者设计模式。

适配器模式的主要作⽤就是把原本不兼容的接⼝,通过适配修改做到统⼀。

原本只是想说偷个懒,没想到不知不觉还用上了设计模式,代码b格一下提高了,leader连忙称赞小伙子不错不错!

总结

其实本文说的招数,其实就是适配器模式,相信大家也理解到这么做的好处了。

在业务开发中我们会经常的需要做不同接⼝或者方法的兼容,那么这个时候就要想到适配器模式。

设计模式其实是前辈们开发中总结的一下通用范式,我们要合理的学习每种设计模式适合场景,解决什么问题。也不要因设计模式而在写代码时强行使用。

在面对各种各样的开发场景,我们要多思考,多沉淀,才可以让自己的代码更优雅,更好扩展。

加油打工人!奥利给

方法入参很复杂,每次调用都要构造BO入参?一招教你自动构造入参相关推荐

  1. el-drawer点击的时候为什么有边框_80%人都有的表格强迫症怎么破,一招教你自动添加表格边框...

    相信对于许多朋友来讲,在使用Excel的时候都会有一个强迫症,那就是新增表格数据的时候,一定会重新添加一次表格边框.如果某些数据每月边框,心里面就会显得非常别扭.今天我们就来学习一下,如何在新增数据的 ...

  2. aspectj 获取方法入参_深入探索编译插桩技术(二、AspectJ)

    本文来自jsonchao的投稿,个人微信:bcce5360 现如今,编译插桩技术已经深入 Android 开发中的各个领域,而 AOP 技术正是一种高效实现插桩的模式,它的出现正好给处于黑暗中的我们带 ...

  3. aop 获取方法入参出参_ASM字节码编程 | JavaAgent+ASM字节码插桩采集方法名称及入参和出参结果并记录方法耗时...

    作者:小傅哥 博客:bugstack.cn ❝ 沉淀.分享.成长,让自己和他人都能有所收获! ❞ 一.前言 在我们实际的业务开发到上线的过程中,中间都会经过测试.那么怎么来保证测试质量呢?比如:提交了 ...

  4. Mybatis方法入参处理

    1,在单个入参的情况下,mybatis不做任何处理,#{参数名} 即可,甚至连参数名都可以不需要,因为只有一个参数,或者使用 Mybatis的内置参数 _parameter. 2,多个入参: 接口方法 ...

  5. spring特殊字符转义和方法入参检测工具类

    由于 Web 应用程序需要联合使用到多种语言,每种语言都包含一些特殊的字符,对于动态语言或标签式的语言而言,如果需要动态构造语言的内容时,一个我们经常会碰到的问题就是特殊字符转义的问题.下面是 Web ...

  6. 新版SpringCloudGateway网关 切面修改方法入参

    通过注解修改方法入参值,一般都是采用实现 org.springframework.web.method.support.HandlerMethodArgumentResolver 接口的 resolv ...

  7. aspect 方法入参 获取_谈谈Spring AOP中@Aspect的高级用法示例

    前言 本文主要跟大家分享介绍了关于Spring AOP中@Aspect的高级用法,下面话不多说了,来随着小编一起看看详细的介绍吧. 1 切点复合运算 支持在切点定义中加入以下运算符进行复合运算: 运算 ...

  8. Spring-AOP @AspectJ进阶之绑定连接点方法入参

    文章目录 概述 实例 概述 我们前面的博文在讲解切点函数时说过args().this().target().@args().@within().@target()和@annotation()这7个函数 ...

  9. xp系统开机自检很久_xp系统每次开机都自检开不了机怎么解决

    许多用户遇到xp系统每次开机都自检,非常烦人,每次都要等待很久时候,影响正常操作,为什么每次开机都要自检?造成故障原因有很多,我们需要从硬件和软件方面考虑.接下来小编和大家分享一下xp系统每次开机都自 ...

最新文章

  1. 【kindeditor】KindEditor获取多个textarea文本框的值并判断非空
  2. jQuery Pagination分页插件--无刷新
  3. 大型高并发高负载网站的系统架构(转)
  4. python学生管理系统-python实现学生成绩管理系统
  5. 四人团-江南行-乌镇东栅旅游
  6. 连接阿里云和容器技术生态 - 阿里云开源容器项目汇总
  7. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task4:评价函数与损失函数
  8. 机器学习 KNN算法_0_丐版_鸢尾花集分类(matlab实现)
  9. jsp 体检信息查询 绕过用户名验证_一篇彻底搞懂jsp
  10. Linux的Open Files设置过小导致程序退出并且Unable to create new native thread
  11. pycharm 右键无法显示unittest框架解决右键只有unittest 运行如何取消右键显示进行普通run...
  12. python最适合做什么-python适合做什么开发?
  13. 移动办公——千脑云电脑 在线存储,中国人的在线办公室
  14. Centos7 虚拟机迁移及扩容
  15. win10修改保存的git用户名和密码
  16. Pygame实现小球躲避
  17. 经典的《Rework》
  18. 五线谱编辑Demo(MFC)
  19. (转)旅游拍照必读:10个经典人像摄影案例@『国家地理』
  20. AndroidStudio很卡怎么办?

热门文章

  1. 尝美食、看演出、听音乐…南亚风情第壹城非遗文化节继续等你玩
  2. bubbles html5游戏源码,html5 canvas弹性气泡爆破 | 撒花动画
  3. chall.tasteless.eu 中的注入题
  4. 【转载】IntelliJ IDEA 完美破解(2099年到期)
  5. Cadence Allegro如何导出与导入规则
  6. 中国SAP 产品的客户名单
  7. python 求最大内切圆和最小外接圆问题
  8. vue 仿写微信公众号自定义菜单
  9. C++循环---数字统计(自学用)
  10. Unity3D中的动态字体和静态字体