最近又看到了Builder構建器模式,想起了以前看的effective java中的講的建立和銷燬對象的方法裏面的一章講到了這個模式,當時不大理解。在網上搜到了好多的博文發現也沒有講清楚真正的設計思想。又看了一遍想了一下,記錄下來。java
主要不理解的地方就是我印象中的三種對象構建模式之間的區別:構造方法,javaBean模式的get、set方法,Builder模式。程序員
1.構造方法模式安全
Public class User{ private String name; private byte sex; private int age; private long phone; public User(String name,byte sex,int age,long phone){ this.name = name; this.sex = sex; this.age = age; this.phone = phone; } }
這種是最經常使用的模式,你們都熟悉。函數
2.javaBean的get,set方法ui
Public class User{ private String name; private byte sex; private int age; private long phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public byte getSex() { return sex; } public void setSex(byte sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getPhone() { return phone; } public void setPhone(long phone) { this.phone = phone; } }
3.Builder構建器模式this
public class Contact { private String name; private byte sex; private int age; private long phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public byte getSex() { return sex; } public void setSex(byte sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getPhone() { return phone; } public void setPhone(long phone) { this.phone = phone; } public static class Builder { private String name; private byte sex; private int age; private long phone; // 構建的步驟 public Builder(String name) { this.name = name; } public Builder age(int val) { age = val; return this; } public Builder sex(byte val) { sex = val; return this; } public Builder phone(long val) { phone = val; return this; } public Contact build() { // 構建,返回一個新對象 return new Contact(this); } } private Contact(Builder b) { age = b.age; sex = b.sex; name = b.name; phone = b.phone; } }
比較:線程
以前一直不理解Builder構建器爲何要建立內部類來實現。更多的人說可使建立對象時代碼更優美,我以爲把javaBean模式的set方法的返回值修改爲當前類自己不是也能夠實現麼。相似設計
public class Contact { private String name; private byte sex; private int age; private long phone; public String getName() { return name; } public Contact setName(String name) { this.name = name; return this; } public byte getSex() { return sex; } public Contact setSex(byte sex) { this.sex = sex; return this; } public int getAge() { return age; } public Contact setAge(int age) { this.age = age; return this; } public long getPhone() { return phone; } public Contact setPhone(long phone) { this.phone = phone; return this; } }
這樣在構建的時候也能夠直接寫new Contact().setAge(0).setName("wer").setPhone(213423423423L).setSex((byte) 1);調試
因此說Builder構建器的真正意義並非代碼優美。code
Effective Java中寫到:遺憾的是,javaBeans模式自身有着很嚴重的缺點。由於構造過程被分到了幾個調用中,在構建過程當中JavaBeans可能處於不一致的狀態。類沒法僅僅經過檢驗構造器參數的有效性來保證一致性。試圖使用處於不一致狀態的對象,將會致使失敗,這種失敗與包含錯誤的代碼截然不同,所以它調試起來十分困難。與此相關的另外一點不足在於,JavaBeans模式阻止了把類作成不可變得可能,這就須要程序員付出額外的努力來確保它的線程安全。
理解了這段意思以後就能夠明白,三種建立對象的方式的區別:
構造方法:能夠保證對象不被修改,可是構建不夠靈活,對於傳不一樣參數個數時須要多個構造函數。
JavaBeans:構建以後可以靈活的改變對象屬性(既是優點也是劣勢,須要根據須要來使用),可是賦值過程不是一次性的,也就不是線程安全的。
Builder構建器:既能保證構建時的靈活性,還能保證建立對象的一次性。這就須要一個內部類來存儲預設置的屬性,在調用bulid()方法的時候一次性構建出來所須要的對象。