1. 程式人生 > >設計模式01-----builder設計模式

設計模式01-----builder設計模式

最近開發任務中碰到一個非常好用的模式,那就是builder設計模式(即建造者設計模式)。

說到builder設計模式,常常會跟可重疊構造器和javabeans模式一起比較說明。下面分別討論:

一. 可重疊構造器模式

可重疊構造器的意思就是有很多的構造器,只是引數個數,引數型別不一樣。舉個到處都在用的例子把:

package com.test.b;

public class Person {
    //必要引數
    private int id;
    private String name;
    //可選引數
    private int age;
    private
String 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(int
id,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模式 程式碼容易編寫 建立物件,必須先創造構建器,造成一定的效能上的開銷