方法入参很复杂,每次调用都要构造BO入参?一招教你自动构造入参
場景
同在互聯網打工的小伙伴們肯定都面臨這樣一種場景:
通用邏輯(被多處調用)我們通常會封裝成一個方法,那這個方法入參正常來說都不會少,(在開發規范中,經常會看到一條"方法入參正常不超過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入参?一招教你自动构造入参的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小d的学习日记 4
- 下一篇: 转换字母大小写(小写转大写)