設計模式01-----builder設計模式
阿新 • • 發佈:2018-11-15
最近開發任務中碰到一個非常好用的模式,那就是builder設計模式(即建造者設計模式)。
說到builder設計模式,常常會跟可重疊構造器和javabeans模式一起比較說明。下面分別討論:
一. 可重疊構造器模式
可重疊構造器的意思就是有很多的構造器,只是引數個數,引數型別不一樣。舉個到處都在用的例子把:
package com.test.b; public class Person { //必要引數 private int id; private String name; //可選引數 private int age; privateString sex; private String phone; public Person(int id,String name) { this(id,name,0); } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", phone=" + phone + "]"; } public Person(intid,String name,int age) { this(id, name,age,""); } public Person(int id, String name, int age, String sex) { this(id, name,0,"",""); } public Person(int id,String name,int age,String sex,String phone) { this.id=id; this.name=name; this.age=age;this.sex=sex; this.phone=phone; } }
雖然測試的時候,只傳入了name和id就可以拿到物件,但是最終打印出來的確是很多引數的一個Person。很多引數的值還不符合常理,需要我們去處理。因此並不方便。這樣的話,我們又不得不傳入更多的引數,可是,我們只想用name和id兩個引數。當然,也可以不用this,就寫很多的構造器,但是引數個數不同而帶來的構造器個數不同,者會導致太多的構造器,不好區分。有些引數都是string,還容易傳錯值,易混淆。
二. javabeans模式
package com.test.b; import java.io.Serializable; public class Person implements Serializable{ //必要引數 private int id; private String name; //可選引數 private int age; private String sex; private String phone; 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
對於程式可讀性以及引數的可控性的考慮我們會是會用javabean來進行類例項化和屬性的賦值。
在使用javabean的時候,尤其是多執行緒時候,獲取同一個javabean(可以通過序列/反序列獲取),那麼下面模擬一個場景:
執行緒A: 獲取person,對其name age sex 就行set操作
同樣執行緒B: 獲取person,對其進行get操作
這時候會出現一種情況,線上程A中沒有set完畢,執行緒B 就開始取相應的屬性
三. builder設計模式
package com.test.b; import java.io.Serializable; public class Person implements Serializable { // 必要引數 private int id; private String name; // 可選引數 private int age; private String sex; private String phone; public Person(Builder builder) { this.id = builder.id; this.name = builder.name; this.age = builder.age; this.sex = builder.sex; this.phone = builder.phone; } public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public String getSex() { return sex; } public String getPhone() { return phone; } public static class Builder { private int id; private String name; private int age; private String sex; private String phone; 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 setSex(String sex) { this.sex = sex; return this; } public Builder setPhone(String phone) { this.phone = phone; return this; } public Person build() { return new Person(this); } } }
在建造者模式中,提供一個輔助的靜態建造器builder,可以在裡面set Person的屬性,與javaBean不同的是,建造者是先set,在通過build例項化person,這樣既可以提高程式碼的閱讀性,也可以防止物件沒有例項化,就被呼叫;不會造成不一致性,同時解決了javabean模式的執行緒安全問題;
四. 比較
重疊構造器模式 | 形式簡單 | 容易出錯,引數表太長不容易控制,而且難以閱讀 |
javaBean模式 | 容易閱讀,建立例項比較容易 | 構造過程被分割到好多個set中容易造成執行緒不安全,導致物件處於不一致的狀態 |
Builder模式 | 程式碼容易編寫 | 建立物件,必須先創造構建器,造成一定的效能上的開銷 |