2016年過(guò)去了,新的一年來(lái)了,大家過(guò)的怎樣呢?16年的小目標(biāo)實(shí)現(xiàn)了嗎?別急,到了17年,你會(huì)發(fā)現(xiàn),還是實(shí)現(xiàn)不了,哈哈哈哈~~~別打我
最近一直在負(fù)責(zé)網(wǎng)絡(luò)框架和數(shù)據(jù)處理部分,也遇到了不少坑,今天就跟大家分享下
大家都知道,我們和服務(wù)器交互的時(shí)候,服務(wù)器返回Json數(shù)據(jù)之后,我們都會(huì)生成對(duì)應(yīng)的實(shí)體類(lèi)去存儲(chǔ)數(shù)據(jù),就是我們所說(shuō)的JavaBean,而對(duì)應(yīng)類(lèi)而言,為了讓客戶(hù)端更容易的去獲取到它的實(shí)例,通常我們都是提供一個(gè)構(gòu)造方法去給別的類(lèi)調(diào)用,但是,我們想下,假如服務(wù)器返回了N個(gè)屬性,我們?cè)诰帉?xiě)實(shí)體類(lèi)的時(shí)候,常用的方式就是寫(xiě)N個(gè)屬性,然后分別生成對(duì)應(yīng)的get和set方法,然后我們別的類(lèi)調(diào)用set方法的時(shí)候,就有下面兩種方式:
1,直接在構(gòu)造方法中傳入
public class LoginBean {
private String id;
private int uid;
private String name;
private String mobile;
private String portrait;
private String realName;
public LoginBean(String id,int uid,String name,String mobile,Strin
portrait,String realName){
this.id=id;
//此處省略
this.realName=realName;
}
2,就是實(shí)例化類(lèi),然后通過(guò)set的方法寫(xiě)入數(shù)據(jù)
LoginBean bean = new LoginBean();
bean.setId(xxx);
//此處省略
bean.setRealName(xxx);
現(xiàn)在我們考慮下,就第一種方式來(lái)說(shuō),假如我有多個(gè)類(lèi)去調(diào)用這個(gè)實(shí)體類(lèi),但是每個(gè)類(lèi)所需要的入?yún)⒍疾灰粯?,有的可?個(gè),有的可能3個(gè),有的可能不需要,如果是按照這個(gè)構(gòu)造方式傳入的話,那么我就必定要傳入N個(gè)參,不需要的參就設(shè)置默認(rèn)值或者null,這時(shí)候有人說(shuō),那我可以提供多個(gè)構(gòu)造方法啊,我覺(jué)得這就是最笨的方法,當(dāng)屬性多的時(shí)候,那就需要多個(gè)構(gòu)造,不僅增加的代碼量,而且還不利于擴(kuò)展,并且當(dāng)別人接手你項(xiàng)目的時(shí)候,也不利于閱讀
如果是第二種方式,的確是比第一種方式好多,不需要多個(gè)構(gòu)造方法,只需在用到的時(shí)候set進(jìn)去就可以,閱讀也方便,但是,遺憾的一點(diǎn)是,JavaBean模式自身就有著比較嚴(yán)重的缺點(diǎn),因?yàn)闃?gòu)造過(guò)程中會(huì)被分到了幾個(gè)調(diào)用中,所以在構(gòu)造之中可能處于不一致,并且還有一點(diǎn)就是,JavaBean阻止了把類(lèi)做成不可變的可能,想了解什么是不可變類(lèi)和可變類(lèi),可以參考下這篇博客:https://my.oschina.net/zzw922cn/blog/487610
簡(jiǎn)單來(lái)說(shuō)就是,不可變類(lèi)就是每個(gè)實(shí)例中所包含的信息必須在創(chuàng)建完成時(shí)就提供,并且在對(duì)象的整個(gè)生命周期內(nèi)固定不變,不可變的類(lèi)比可變類(lèi)更加實(shí)現(xiàn),使用,也不容易出錯(cuò),具體自己可以去了解下,這里不做深入的說(shuō)明
第二種方式是在構(gòu)造完成之后,在去寫(xiě)入值,跟不可變類(lèi)就相反了,那么有沒(méi)有一種方式,既可以保證不需要像第一種方式那樣編寫(xiě)多個(gè)構(gòu)造,又能解決第二種方式的問(wèn)題呢?這就本文的重點(diǎn),Builder模式
Builder模式
Builder模式又叫構(gòu)造者模式,既然我們既要像第一種方式那樣可以直接在構(gòu)造器入?yún)?,又要避免第二種方式的問(wèn)題,是不是有點(diǎn)棘手呢?它是怎么實(shí)現(xiàn)這種處理的呢?先看它的實(shí)現(xiàn)
public class Test {
private final String id;
private final String uid;
private Test(Builder builder) {
this.id = builder.id;
this.uid = builder.uid;
}
public static class Builder {
private String id;
private String uid;
public Builder setId(String id) {
this.id = id;
return this;
}
public Builder setUid(String uid) {
this.uid = uid;
return this;
}
public Test build() {
return new Test(this);
}
@Override
public String toString() {
return "Builder{" +
"id='" + id + '\'' +
", uid='" + uid + '\'' +
'}';
}
}
@Override
public String toString() {
return "Test{" +
"id='" + id + '\'' +
", uid='" + uid + '\'' +
'}';
}
}
我們不難發(fā)現(xiàn),我們并沒(méi)有直接生成想要的對(duì)象,而是讓客戶(hù)端利用所有必要的參數(shù)調(diào)用構(gòu)造器,得到一個(gè)builder對(duì)象,然后再調(diào)用builder的set中方法,來(lái)設(shè)置參數(shù),這樣就保證了在生成實(shí)例的時(shí)候直接就綁定了數(shù)據(jù),我們看看怎么調(diào)用:
public static void main(String [] args){
Test test = new Test.Builder()
.setId("0")
.setUid("fadf")
.build();
System.out.print(test.toString());
}
是不是很像Rxjava的連式結(jié)構(gòu),客戶(hù)端調(diào)用無(wú)參的build方法生成了對(duì)象,因?yàn)樵谏蓪?duì)象之前就已經(jīng)把數(shù)據(jù)set進(jìn)去了,這就保證了類(lèi)的不可變,也就是說(shuō),當(dāng)我們需要重新去set數(shù)據(jù)的時(shí)候,得重新去生成新的對(duì)象然后進(jìn)行build,還有的是,這樣的代碼更加的清晰,便于閱讀,并且很靈活,builder可以有多個(gè)可變的參數(shù),這也解決了第一種生成多個(gè)構(gòu)造器的問(wèn)題,總而言之,如果類(lèi)的構(gòu)造器具有多個(gè)參數(shù)或者參數(shù)多變的情況下,這樣設(shè)計(jì)就是個(gè)不錯(cuò)的選擇
好了,這篇文章就到這來(lái),祝大家新的一年了,新年快樂(lè),工作順利,也祝大家雞年大吉吧,嘿嘿嘿~~~