溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

當(dāng)構(gòu)造方法的參數(shù)過(guò)多時(shí)怎么使用builder模式

發(fā)布時(shí)間:2021-10-18 09:46:18 來(lái)源:億速云 閱讀:208 作者:柒染 欄目:web開(kāi)發(fā)

這篇文章將為大家詳細(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ò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI