學(xué)了這個(gè),三歪再也不想寫(xiě)各種setter了
今天又來(lái)給大家吹一下逼。
三歪在公司里邊也看了不少的系統(tǒng)了,看到結(jié)構(gòu)清晰、代碼清晰的系統(tǒng)時(shí)會(huì)贊嘆能寫(xiě)出這種代碼的人是真的牛逼??吹絹y七八糟的代碼又不寫(xiě)注釋的時(shí)候也會(huì)吐槽:“這寫(xiě)的是啥啊”
多看別人的代碼,總會(huì)有不同的發(fā)現(xiàn)和體會(huì)。
最近看別人項(xiàng)目的時(shí)候,發(fā)現(xiàn)會(huì)有這種寫(xiě)法:
MessageTask?task?=?MessageTask.builder()
??.content("關(guān)注?Java3y?吧?>>?")
??.messageId(String.valueOf(ThreadLocalRandom.current().nextLong()))
??.taskId("3y")
??.taskName("一起來(lái)玩")
??.build();
System.out.println(task.toString());
看代碼其實(shí)很容易看出它在干嘛,就是在創(chuàng)建MessageTask這個(gè)對(duì)象。
平時(shí)我們初學(xué)的時(shí)候,如果要?jiǎng)?chuàng)建這個(gè)對(duì)象會(huì)怎么寫(xiě)?一般會(huì)有兩種方法:
- 將屬性配在構(gòu)造函數(shù)上,然后直接調(diào)構(gòu)造器,傳入?yún)?shù)
- 調(diào)用多個(gè)
set方法
//?構(gòu)造器傳入屬性
MessageTask?messageTask?=?new?MessageTask("3y",?"關(guān)注?Java3y?吧?>>",?
??????????????????????????????????????????String.valueOf(ThreadLocalRandom.current().nextLong()),?"一起來(lái)玩");
//?調(diào)用各種的set方法
MessageTask?messageTask?=?new?MessageTask();
messageTask.setTaskId("3y");
messageTask.setContent("關(guān)注?Java3y?吧?>>");
messageTask.setMessageId(String.valueOf(ThreadLocalRandom.current().nextLong()));
messageTask.setTaskName("一起來(lái)玩");
日常使用的話,應(yīng)該是多次調(diào)用set方法比較多的(應(yīng)該都是這樣的吧)。
從代碼層面上,構(gòu)造器傳參的代碼是最簡(jiǎn)短的,但在現(xiàn)實(shí)層面上我們很難每次都可以通過(guò)構(gòu)造器傳參的方式去完成對(duì)象的創(chuàng)建(更多的時(shí)候每個(gè)對(duì)象的屬性都是不一致的)。
構(gòu)造器的代碼看起來(lái)非常短,但閱讀起來(lái)不太友好(我得去看每個(gè)參數(shù)是什么意思);
而set方法寫(xiě)起來(lái)不太方便,如果對(duì)象的屬性較多,也會(huì)有一大串的set代碼。
而文章最開(kāi)始的builer鏈?zhǔn)?/strong>調(diào)用就很舒服,我一看這代碼就知道這肯定是哪種我不知道的設(shè)計(jì)模式。
于是我一查,原來(lái)這就叫做建造者模式。
怎么實(shí)現(xiàn)建造者模式?
建造者模式更多的是寫(xiě)法上的不同,從代碼結(jié)構(gòu)層面上其實(shí)沒(méi)有很大的區(qū)別,只是看起來(lái)會(huì)更清爽一些。
那怎么實(shí)現(xiàn)建造者模式呢?其實(shí)也非常簡(jiǎn)單:
- 在domain類(lèi)上創(chuàng)建一個(gè)靜態(tài)內(nèi)部類(lèi) Builder,Builder擁有domain所有的屬性
- 在domain類(lèi)上創(chuàng)建一個(gè)
private的構(gòu)造函數(shù),參數(shù)為Builder類(lèi)型,里邊將Builder的屬性賦值給domain的屬性 - 在Builder內(nèi)部類(lèi)創(chuàng)建domain屬性的賦值方法,返回值是Builder
- Builder內(nèi)部類(lèi)創(chuàng)建一個(gè)
build方法,返回domain實(shí)例
下面我們來(lái)實(shí)現(xiàn)一下吧,首先創(chuàng)建一個(gè)靜態(tài)內(nèi)部類(lèi)Builder,并且內(nèi)部類(lèi)Builder擁有domain的所有屬性:
public?class?MessageTask?{
????private?String?taskId;
????private?String?content;
????private?String?messageId;
????private?String?taskName;
?
???//?創(chuàng)建內(nèi)部類(lèi)
????public?static?class?Builder{
????????private?String?taskId;
????????private?String?content;
????????private?String?messageId;
????????private?String?taskName;
????}
}
在domain類(lèi)上創(chuàng)建一個(gè)private的構(gòu)造函數(shù),參數(shù)為Builder類(lèi)型,里邊是將Builder的屬性賦值給domain的屬性:
public?class?MessageTask?{
????private?String?taskId;
????private?String?content;
????private?String?messageId;
????private?String?taskName;
???//?增加private構(gòu)造函數(shù)
????private?MessageTask(Builder?builder)?{
????????this.taskId?=?builder.taskId;
????????this.content?=?builder.content;
????????this.messageId?=?builder.messageId;
????????this.taskName?=?builder.taskName;
????}
????public?static?class?Builder{
????????private?String?taskId;
????????private?String?content;
????????private?String?messageId;
????????private?String?taskName;
????}
}
在Builder內(nèi)部類(lèi)創(chuàng)建domain屬性的賦值方法,返回值是Builder
public?class?MessageTask?{
????private?String?taskId;
????private?String?content;
????private?String?messageId;
????private?String?taskName;
????private?MessageTask(Builder?builder)?{
????????this.taskId?=?builder.taskId;
????????this.content?=?builder.content;
????????this.messageId?=?builder.messageId;
????????this.taskName?=?builder.taskName;
????}
????public?static?class?Builder{
????????private?String?taskId;
????????private?String?content;
????????private?String?messageId;
????????private?String?taskName;
????????//?賦值屬性的方法(返回的是Builder)
????????public?Builder?setTaskId(String?taskId)?{
????????????this.taskId?=?taskId;
????????????return?this;
????????}
????????public?Builder?setContent(String?content)?{
????????????this.content?=?content;
????????????return?this;
????????}
????????public?Builder?setMessageId(String?messageId)?{
????????????this.messageId?=?messageId;
????????????return?this;
????????}
????????public?Builder?setTaskName(String?taskName)?{
????????????this.taskName?=?taskName;
????????????return?this;
????????}
????}
}
在Builder內(nèi)部類(lèi)創(chuàng)建一個(gè)builde方法,返回domain實(shí)例
public?class?MessageTask?{
????private?String?taskId;
????private?String?content;
????private?String?messageId;
????private?String?taskName;
????private?MessageTask(Builder?builder)?{
????????this.taskId?=?builder.taskId;
????????this.content?=?builder.content;
????????this.messageId?=?builder.messageId;
????????this.taskName?=?builder.taskName;
????}
????public?static?class?Builder{
????????private?String?taskId;
????????private?String?content;
????????private?String?messageId;
????????private?String?taskName;
??????
????????public?Builder?setTaskId(String?taskId)?{
????????????this.taskId?=?taskId;
????????????return?this;
????????}
????????public?Builder?setContent(String?content)?{
????????????this.content?=?content;
????????????return?this;
????????}
????????public?Builder?setMessageId(String?messageId)?{
????????????this.messageId?=?messageId;
????????????return?this;
????????}
????????public?Builder?setTaskName(String?taskName)?{
????????????this.taskName?=?taskName;
????????????return?this;
????????}
??????
????//?創(chuàng)建build方法,返回實(shí)例
????????public?MessageTask?build()?{
????????????return?new?MessageTask(this);
????????}
????}
}
使用方式:先創(chuàng)建Builder對(duì)象,然后用Builder去賦值,最后再調(diào)用build()返回真正的實(shí)例:
MessageTask.Builder?builder?=?new?MessageTask.Builder();
MessageTask?task?=?builder.setContent("關(guān)注?Java3y?吧?>>")
??.setTaskId("3y")
??.setTaskName("一起來(lái)玩")
??.setMessageId(String.valueOf(ThreadLocalRandom.current().nextLong()))
??.build();
借助工具使用建造者模式
從使用的角度感覺(jué)是好用了,代碼也清爽了。其實(shí)可以發(fā)現(xiàn)的是,我們都把邏輯寫(xiě)到了Domain類(lèi)上,這寫(xiě)起來(lái)肯定是需要花時(shí)間的。
我第一印象是:這種這么通用的東西,肯定是有可以一鍵生成的方法的,于是我瞄準(zhǔn)了Lombok
果不其然,我們?nèi)绻褂昧?code style="font-size:14px;background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(40,202,113);">Lombok后,在類(lèi)上加上一個(gè)注解@Builder就可以使用建造者模式的代碼了,非常方便
@Builder
@Data
public?class?MessageTask?{
????private?String?taskId;
????private?String?content;
????private?String?messageId;
????private?String?taskName;
}
又想了一下,IDEA這么強(qiáng)大,感覺(jué)IDEA也有辦法去生成Builder,也果不其然:

做個(gè)小調(diào)查:
- 如果你之前已經(jīng)了解過(guò)了建造者模式,你在項(xiàng)目中有用嗎?
- 如果你看了這篇文章才了解到了建造者模式,你在以后會(huì)用嗎?
我個(gè)人是看團(tuán)隊(duì)的代碼風(fēng)格的,如果原有已經(jīng)是各種set去構(gòu)造對(duì)象,那我就不會(huì)再修改了。如果是新寫(xiě)的業(yè)務(wù),會(huì)使用建造者模式。
各類(lèi)知識(shí)點(diǎn)總結(jié)
下面的文章都有對(duì)應(yīng)的原創(chuàng)精美PDF,在持續(xù)更新中,可以來(lái)找我催更~
- 92頁(yè)的Mybatis
- 129頁(yè)的多線程
- 141頁(yè)的Servlet
- 158頁(yè)的JSP
- 76頁(yè)的集合
- 64頁(yè)的JDBC
- 105頁(yè)的數(shù)據(jù)結(jié)構(gòu)和算法
- 142頁(yè)的Spring
- 58頁(yè)的過(guò)濾器和監(jiān)聽(tīng)器
- 30頁(yè)的HTTP
- 42頁(yè)的SpringMVC
- Hibernate
- AJAX
- Redis
- ......
掃碼或者微信搜Java3y?免費(fèi)領(lǐng)取原創(chuàng)思維導(dǎo)圖、精美PDF。在公眾號(hào)回復(fù)「888」領(lǐng)取,PDF內(nèi)容純手打有任何不懂歡迎來(lái)問(wèn)我。
原創(chuàng)電子書(shū)
原創(chuàng)思維導(dǎo)圖

![]() |
|


