欧美日韩国产一区二区三区不卡,欧洲一区二区三区精品,日韩一区不卡,成人国产二区

builder(java:其實(shí)你并不會(huì)用Builder)

時(shí)間:2024-11-23 21:47:15 閱讀:6

java:但是你并不會(huì)用Builder

天生器形式在Java使用步驟中十分盛行。但它常常被各位曲解和錯(cuò)誤地使用,從而招致運(yùn)轉(zhuǎn)時(shí)錯(cuò)誤。

讓我們記取使用Builder的目標(biāo):僅在某些目標(biāo)中設(shè)置必要的字段,并將其他字段設(shè)置為默許值。比如,假如我們正在準(zhǔn)備設(shè)置目標(biāo),那么僅變動(dòng)必要的參數(shù)并將其他參數(shù)設(shè)置為默許值會(huì)很便利。

而當(dāng)Builder是反形式時(shí)

很多開(kāi)發(fā)職員只選擇了Builder形式的一局部:可以單獨(dú)設(shè)置字段。第二局部:其他字段存在公道的默許值-通常會(huì)被忽略。

后果,很容易取得不完備的(局部初始化的)POJO。為了緩解此成績(jī),我們對(duì)build()辦法舉行了反省,最初約莫本人都沒(méi)發(fā)覺(jué)啥成績(jī)但就是出錯(cuò)。此時(shí)如今,主要的侵害以前形成:反省轉(zhuǎn)移到了運(yùn)轉(zhuǎn)時(shí)間上。為確保統(tǒng)統(tǒng)正常,我們必要添加自用測(cè)試以掩蓋創(chuàng)建POJO的代碼中的一切實(shí)行途徑。

怎樣修復(fù)POJO的天生器?

起首,讓我們界說(shuō)目標(biāo)。這里的目標(biāo)是將反省前往到編譯時(shí)。假如未構(gòu)建完備POJO的代碼無(wú)法經(jīng)過(guò)編譯,則將不必要自用測(cè)試,也無(wú)需在build()辦法中實(shí)行反省。但最緊張的是,平常我們事情起來(lái)就更輕松。有更多時(shí)間摸魚(yú)了。

那么,怎樣做到這一點(diǎn)呢?最分明的辦法是使用Fluent API形式。Fluent API有兩個(gè)局部(特地說(shuō)一句,就像Builder一樣):提供一種便利的辦法來(lái)調(diào)用鏈中的辦法(這兩個(gè)局部Fluent API和Builder都相反),并將鏈中的每個(gè)后續(xù)調(diào)用都限定為僅允許的辦法集。

第二局部是我們所要說(shuō)的局部。經(jīng)過(guò)限定在構(gòu)建POJO的每個(gè)步調(diào)中可以調(diào)用的辦法集,我們可以欺壓實(shí)行特定的調(diào)用序列,并build()僅在設(shè)置了一切字段時(shí)才啟用對(duì)辦法的調(diào)用。如此,我們將一切反省移回編譯時(shí)間。作為便利的反作用,還確保構(gòu)建特定POJO的一切地點(diǎn)看起來(lái)都相反。如此,發(fā)覺(jué)錯(cuò)誤轉(zhuǎn)達(dá)的參數(shù)或比力代碼修訂之間的變動(dòng)將愈加容易。

為了區(qū)分傳統(tǒng)的Builder和帶有Fluent API的Builder,我將后者稱為Fluent Builder

假定我們要為如下所示的簡(jiǎn)便bean創(chuàng)建Fluent Builder:

public class SimpleBean { private final int index; private final String name; public SimpleBean(final int index, final String name) { this.index = index; this.name = name; } public int index() { return index; } public String name() { return name; } }

在此示例中,我使用了Java 紀(jì)錄獲取器的稱呼商定。在Java 14中,此類可以聲明為紀(jì)錄,因此必要的樣板代碼將大大變小。

讓我們添加一個(gè)構(gòu)建器。第一步很傳統(tǒng):

... public static SimpleBeanBuilder builder() { return new SimpleBeanBuilder(); } ...

讓我們起首完成一個(gè)傳統(tǒng)的天生器,如此會(huì)愈加清晰Fluent Builder代碼是怎樣派生的。傳統(tǒng)的Builder類如下所示:

... private static class SimpleBeanBuilder { private int index; private String name; public SimpleBeanBuilder setIndex(final int index) { this.index = index; return this; } public SimpleBeanBuilder setName(final String name) { this.name = name; return this; } public SimpleBean build() { return new SimpleBean(index, name); } } ...

一個(gè)緊張的察看:每個(gè)setter前往此值,這又允許此調(diào)用的用戶調(diào)用builder中可用的每個(gè)辦法。這是成績(jī)的本源,由于build()在設(shè)置一切必要字段之前,允許用戶過(guò)早調(diào)用該辦法。

為了制造Fluent Builder,我們必要將約莫的選擇限定為僅允許的選擇,因此必需準(zhǔn)確使用Builder。由于我們正在思索必要設(shè)置一切字段的情況,因此在每個(gè)構(gòu)建步調(diào)中,僅有一種辦法可用。為此,我們可以前往自用接口,而不是this讓Builder完成一切這些接口:

... public static SimpleBeanBuilder0 builder() { return new SimpleBeanBuilder(); } ... private static class SimpleBeanBuilder implements SimpleBeanBuilder0, SimpleBeanBuilder1, SimpleBeanBuilder2 { private int index; private String name; public SimpleBeanBuilder1 setIndex(final int index) { this.index = index; return this; } public SimpleBeanBuilder2 setName(final String name) { this.name = name; return this; } public SimpleBean build() { return new SimpleBean(index, name); } public interface SimpleBeanBuilder0 { SimpleBeanBuilder1 setIndex(final int index); } public interface SimpleBeanBuilder1 { SimpleBeanBuilder2 setName(final String name); } public interface SimpleBeanBuilder2 { SimpleBean build(); } }

這模板有點(diǎn)丑,換個(gè)辦法。

第一步是中止完成接口,而是前往完成這些接口的匿名類:

... public static SimpleBeanBuilder builder() { return new SimpleBeanBuilder(); } ... private static class SimpleBeanBuilder { public SimpleBeanBuilder1 setIndex(int index) { return new SimpleBeanBuilder1() { @Override public SimpleBeanBuilder2 setName(final String name) { return new SimpleBeanBuilder2() { @Override public SimpleBean build() { return new SimpleBean(index, name); } }; } }; } public interface SimpleBeanBuilder1 { SimpleBeanBuilder2 setName(final String name); } public interface SimpleBeanBuilder2 { SimpleBean build(); } }

如此很多了。我們可以再次寧?kù)o地SimpleBeanBuilder從該builder()辦法前往,由于此類僅公開(kāi)一個(gè)辦法,并且不允許用戶過(guò)早構(gòu)建實(shí)例。但更緊張的是,我們可以省略構(gòu)建器中的整個(gè)設(shè)置器和可變字段樣板,從而大大變小了代碼量。這是約莫的,由于我們?cè)诳梢?jiàn)和可拜候一切設(shè)置器參數(shù)的范圍內(nèi)創(chuàng)建了匿名類。

就代碼總數(shù)而言,天生的代碼與原始Builder完成相當(dāng)。

但這還不是全部。由于一切匿名類實(shí)踐上都是僅包含一種辦法的接口的完成,因此我們可以用lambda交換匿名類:

private static class SimpleBeanBuilder { public SimpleBeanBuilder1 setIndex(int index) { return name -> () -> new SimpleBean(index, name); } public interface SimpleBeanBuilder1 { SimpleBeanBuilder2 setName(final String name); } public interface SimpleBeanBuilder2 { SimpleBean build(); } }

注意,剩余的SimpleBeanBuilder類與其他構(gòu)建器接口十分相似,因此也可以將其交換為lambda:

public static SimpleBeanBuilder builder() { return index -> name -> () -> new SimpleBean(index, name); } public interface SimpleBeanBuilder { SimpleBeanBuilder1 setIndex(int index); } public interface SimpleBeanBuilder1 { SimpleBeanBuilder2 setName(final String name); } public interface SimpleBeanBuilder2 { SimpleBean build(); }

最初:

  • 在SimpleBeanBuilder接口內(nèi)挪動(dòng)接口,并對(duì)接口舉行一些重定名。由于這些接口很少會(huì)顯如今用戶代碼中,因此我們可以為其使用一些標(biāo)準(zhǔn)化的定名辦法,并簡(jiǎn)化代碼的主動(dòng)天生。
  • 重定名設(shè)置器,由于不必要Java Bean定名商定,由于這里沒(méi)有獲取器。
  • 版本()辦法是沒(méi)有必要了。在最初的完成中,它表現(xiàn)以前完成POJO的組裝,但這不再是必需的,由于一旦設(shè)置了最初一個(gè)字段,便擁有了構(gòu)建POJO實(shí)例的一切必要細(xì)節(jié)。

底下是SimpleBean使用一切這些變動(dòng)之后的完備代碼:

public class SimpleBean { private final int index; private final String name; private SimpleBean(final int index, final String name) { this.index = index; this.name = name; } public int index() { return index; } public String name() { return name; } public static Builder builder() { return index -> name -> new SimpleBean(index, name); } public interface Builder { Stage1 index(int index); interface Stage1 { SimpleBean name(final String name); } } }

實(shí)踐上實(shí)行少數(shù)利用的代碼很少,大大多完成是一堆接口聲明。添加,變動(dòng)或刪除字段十分簡(jiǎn)便,由于觸及的代碼很少。

關(guān)于尚未習(xí)氣使用深層嵌套lambda的用戶,此代碼乍一看約莫會(huì)比力困難,但這是履歷成績(jī)。別的,無(wú)需手動(dòng)編寫(xiě)此類代碼,由于我們可以將此職責(zé)卸載到IDE(就像我們使用傳統(tǒng)構(gòu)建器一樣)。

使用上述辦法,我們可以用Fluent Builders代替?zhèn)鹘y(tǒng)的Builders,并經(jīng)過(guò)Fluent API形式寧?kù)o性取得Builder的簡(jiǎn)便利用。

版權(quán)聲明:本文來(lái)自互聯(lián)網(wǎng)整理發(fā)布,如有侵權(quán),聯(lián)系刪除

原文鏈接:http://m.freetextsend.comhttp://m.freetextsend.com/wangluozixun/55899.html


Copyright ? 2021-2022 All Rights Reserved 備案編號(hào):閩ICP備2023009674號(hào) 網(wǎng)站地圖 聯(lián)系:dhh0407@outlook.com

主站蜘蛛池模板: 勃利县| 南漳县| 云南省| 永顺县| 甘德县| 许昌县| 恩施市| 右玉县| 桐城市| 林口县| 六盘水市| 青海省| 敦化市| 浪卡子县| 霸州市| 武夷山市| 崇文区| 客服| 府谷县| 姜堰市| 临朐县| 梨树县| 长垣县| 新建县| 沙坪坝区| 张掖市| 江门市| 富蕴县| 夏津县| 卓尼县| 绵阳市| 永宁县| 巫溪县| 泸州市| 英超| 新泰市| 内江市| 同德县| 阳山县| 清涧县| 茌平县|