您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)當(dāng)構(gòu)造方法的參數(shù)過(guò)多時(shí)怎么使用builder模式,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
一、傳統(tǒng)方式的缺點(diǎn)
1、可伸縮構(gòu)造方法
可伸縮構(gòu)造方法就是我們平時(shí)書(shū)寫(xiě)最常見(jiàn)的那種,請(qǐng)看下文代碼;
public class Student { private int id; //必要 private String name;//必要 private int age; //可選 private int sclass; //可選 private int height;//可選 private float weight;//可選 private float score;//可選 //構(gòu)造函數(shù)1:默認(rèn)構(gòu)造方法 public Student() {}; //構(gòu)造方法2:必要字段構(gòu)造方法 public Student(int id, String name) { this.id = id; this.name = name; } //構(gòu)造方法3:全部字段構(gòu)造方法 public Student(int id, String name, int age, int sclass, int height, float weight, float score) { super(); this.id = id; this.name = name; this.age = age; this.sclass = sclass; this.height = height; this.weight = weight; this.score = score; } }
下面如果我們要?jiǎng)?chuàng)建一個(gè)Student類,一般這樣創(chuàng)建,看下面代碼:
public class Main { public static void main(String[] args) { //1、可伸縮構(gòu)造方法 Student student1 = new Student(); Student student2 = new Student(1,"愚公要移山"); Student student3 = new Student(2,"愚公要移山",18,1,175,120,99); } }
現(xiàn)在我們列舉了一個(gè)具有七個(gè)字段的例子,比較容易理解,現(xiàn)在我們來(lái)分析一下,他有什么缺點(diǎn):
缺點(diǎn)1:反轉(zhuǎn)字段,編譯器不會(huì)報(bào)錯(cuò)
比如上面的字段里面有一個(gè)weight和一個(gè)score,都是float類型,如果再new一個(gè)Student類時(shí),不小心寫(xiě)反了,編譯器不會(huì)察覺(jué)。
缺點(diǎn)2:難以理解
這里只是七個(gè)字段,如果有十幾個(gè),我們就需要不斷地去Student類中去查看,看看第幾個(gè)參數(shù)應(yīng)該寫(xiě)哪些東西,實(shí)在是比較麻煩。用戶在看到這個(gè)Student(2,"愚公要移山",18,1,175,120,99)無(wú)法理解每一個(gè)字段屬性代表的是什么含義。
缺點(diǎn)3:不想設(shè)置的參數(shù),卻不得不設(shè)置值
有時(shí)候我們的Student只想著設(shè)置ID、name和age字段,其他的無(wú)關(guān)緊要,但是這種模式必須要設(shè)置所有的屬性值。
既然上面有這些缺點(diǎn),我們可能還想到另外一種方式,那就是javaBean。
2、javaBean模式
先看javaBean模式如何寫(xiě)的。
public class Student { private int id; //必要 private String name;//必要 private int age; //可選 private int sclass; //可選 private int height;//可選 private float weight;//可選 private float score;//可選 //構(gòu)造函數(shù)1:默認(rèn)構(gòu)造方法 public Student() {} //getter和setter方法 public int getId() {return id;} public void setId(int id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} public int getAge() {return age;} public void setAge(int age) {this.age = age;} public int getSclass() {return sclass;} public void setSclass(int sclass) {this.sclass = sclass;} public int getHeight() {return height;} public void setHeight(int height) {this.height = height;} public float getWeight() {return weight;} public void setWeight(float weight) {this.weight = weight;} public float getScore() {return score;} public void setScore(float score) {this.score = score;}; }
這種模式,看起來(lái)還比較舒服,只是設(shè)置了相應(yīng)的getter和setter方法。再來(lái)看看如何使用這種方式去new一個(gè)Student類。
public class Main { public static void main(String[] args) { //2、javaBean模式 Student student1 = new Student(); student1.setId(1); student1.setName("愚公要移山"); student1.setSclass(1); student1.setWeight(180); student1.setHeight(175); student1.setScore(100); student1.setAge(20); } }
這樣看起來(lái)還可以,不過(guò)這只是我自己一個(gè)一個(gè)敲出來(lái)的。實(shí)際在用的時(shí)候就知道同樣惡心了,現(xiàn)在來(lái)總結(jié)一波他的缺點(diǎn)。
缺點(diǎn)1:構(gòu)造過(guò)程中 JavaBean可能處于不一致的狀態(tài)
JavaBeans 模式本身有嚴(yán)重的缺陷。由于構(gòu)造方法在多次調(diào)用中被分割,所以在構(gòu)造過(guò)程中 JavaBean 可能處于不一致的狀態(tài)。該類沒(méi)有通過(guò)檢查構(gòu)造參數(shù)參數(shù)的有效性來(lái)執(zhí)行一致性的選項(xiàng)。在不一致的狀態(tài)下嘗試使用對(duì)象可能會(huì)導(dǎo)致與包含 bug 的代碼大相徑庭的錯(cuò)誤,因此很難調(diào)試。
說(shuō)一下我對(duì)其的理解,在上面的例子中,我們的student1對(duì)象被多次調(diào)用了set方法,但是可能有時(shí)候在用到這個(gè)bean時(shí),剩下的setter方法還沒(méi)有做完,于是再次調(diào)用時(shí)發(fā)現(xiàn)同一個(gè)javaBean呈現(xiàn)出了兩種狀態(tài)。于是處于一種不一致的狀態(tài)。
缺點(diǎn)2:無(wú)法保證javaBean的不可變性
使用第一種模式可伸縮構(gòu)造方法實(shí)例化之后不會(huì)更改可變性,所有的數(shù)據(jù)都是確定好了的。也可以保證線程安全。但是提供了setter方法,就不能保證了。比如:
public class Main { public static void main(String[] args) { //2、javaBean模式 Student student1 = new Student(); student1.setId(1); student1.setName("愚公要移山"); student1.setSclass(1); student1.setWeight(180); student1.setHeight(175); student1.setScore(100); student1.setAge(20); System.out.println(student1.getName()); student1.setName("馮冬冬"); System.out.println(student1.getName()); } } //輸出結(jié)果:愚公要移山 馮冬冬
可以看到,我們可以對(duì)Student對(duì)象設(shè)置多次name,前后是不一致的狀態(tài)。
既然前面兩種都存在各種各樣的問(wèn)題。現(xiàn)在我們?cè)賮?lái)看今天的主題builder模式,
二、builder模式
還是老樣子,我們先看看builder模式長(zhǎng)得什么樣子。再來(lái)分析一下他的優(yōu)缺點(diǎn)。
public class Student { private int id; // 必要 private String name;// 必要 private int age; // 可選 private int sclass; // 可選 private int height;// 可選 private float weight;// 可選 private float score;// 可選 public Student(Builder builder) { this.id = builder.id; this.name = builder.name; this.age = builder.age; this.sclass = builder.sclass; this.height = builder.height; this.weight = builder.weight; this.score = builder.score; } public static class Builder { private int id; // 必要 private String name;// 必要 private int age; // 可選 private int sclass; // 可選 private int height;// 可選 private float weight;// 可選 private float score;// 可選 // 必要參數(shù)的構(gòu)造方法 public Builder(int id, String name) { this.id = id; this.name = name; } public Builder setId(int id) { this.id = id; return this; } public Builder setName(String name) { this.name = name; return this; } public Builder setAge(int age) { this.age = age; return this; } public Builder setSclass(int sclass) { this.sclass = sclass; return this; } public Builder setHeight(int height) { this.height = height; return this; } public Builder setWeight(float weight) { this.weight = weight; return this; } public Builder setScore(float score) { this.score = score; return this; } // 對(duì)外提供的 public Student build() { return new Student(this); } } }
上面的代碼是在內(nèi)部構(gòu)造了一個(gè)Builder類,然后我們看看如何去使用。
public class Main { public static void main(String[] args) { //3、Builder模式 Student stu = new Student.Builder(1, "愚公要移山") .setAge(20) .setHeight(175) .setSclass(1) .setScore(100) .setWeight(100).build(); } }
這本書(shū)中對(duì)其的缺點(diǎn)也進(jìn)行了介紹,很直觀可以看到,Student類中的代碼量增加了很多。但是Student類,我們只需要寫(xiě)一次,這卻為我們創(chuàng)建對(duì)象帶來(lái)了方便。
優(yōu)點(diǎn)1:不存在反轉(zhuǎn)字段的情況
上面可以看出,每次添加新字段值的時(shí)候是通過(guò)set方式進(jìn)行的。具有javaBean的優(yōu)點(diǎn)。
優(yōu)點(diǎn)2:靈活構(gòu)造參數(shù)
我們把必要的字段一寫(xiě),那些非必要的字段我們可以自己選擇是不是要set。
優(yōu)點(diǎn)3:不存在不一致?tīng)顟B(tài)
使用builder模式,對(duì)象的創(chuàng)建必須要等到build完成才可以。
優(yōu)點(diǎn)4:使用靈活
單個(gè) builder 可以重復(fù)使用來(lái)構(gòu)建多個(gè)對(duì)象。builder 的參數(shù)可以在構(gòu)建方法的調(diào)用之間進(jìn)行調(diào)整,以改變創(chuàng)建的對(duì)象。builder 可以在創(chuàng)建對(duì)象時(shí)自動(dòng)填充一些屬性,例如每次創(chuàng)建對(duì)象時(shí)增加的序列號(hào)。
缺點(diǎn):
為了創(chuàng)建對(duì)象,首先必須創(chuàng)建它的 builder。雖然創(chuàng)建這個(gè) builder 的成本在實(shí)踐中不太可能被注意到,但在性能關(guān)鍵的情況下可能會(huì)出現(xiàn)問(wèn)題。而且,builder 模式比伸縮構(gòu)造方法模式更冗長(zhǎng),因此只有在有足夠的參數(shù)時(shí)才值得使用它,比如四個(gè)或更多。
但是,如果從構(gòu)造方法或靜態(tài)工廠開(kāi)始,并切換到 builder,當(dāng)類演化到參數(shù)數(shù)量失控的時(shí)候,過(guò)時(shí)的構(gòu)造方法或靜態(tài)工廠就會(huì)面臨尷尬的處境。因此,所以,最好從一開(kāi)始就創(chuàng)建一個(gè) builder。
關(guān)于當(dāng)構(gòu)造方法的參數(shù)過(guò)多時(shí)怎么使用builder模式就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。