java中Builder構建器的理解

最近又看到了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()方法的時候一次性構建出來所須要的對象。

相關文章
相關標籤/搜索