本文索引
一、簡介
二、建立 Builder
三、結論
日期:2020 年 8 月 7 日
一、簡介
在物件導向程式設計中,我們很常遇到需要撰寫自己的類別(Class),
而當遇到較為複雜的類別時,在撰寫建構子或再給予初值時,就很常會遇到有些值需要初值有些則不需要
,又或者是許多的值需要傳入建構子裡,造成程式碼的冗長與難以閱讀。
而這裡就有一個設計模式叫做 建立者模式(Builder Pattern),來解決此問題,有缺點也有優點,我們先看以下的例子:
我們先定義一個個人資料類別:
class Person{
private final String ID; //身分字字號
private String name; //名稱
private int gender; //性別
private String residentAddress; //戶籍地址
private String mailingAddress; //通訊住址
private String email; //電子郵件
private String phone; //電話
private String mobilePhone; //手機
/** 建構子 1
* @param ID 身分證
* @param name 姓名
* @param gender 性別 */
public Person(String ID, String name, int gender){
this.ID = ID;
this.name = name;
this.gender = gender;
}
/** 建構子 2
* @param ID 身分證
* @param name 姓名
* @param gender 性別
* @param residentAddress 戶籍地址
* @param mailingAddress 通訊地址
* @param email 電子郵件
* @param phone 電話
* @param mobilePhone 手機 */
public Person(String ID, String name, int gender, String residentAddress, String mailingAddress, String email, String phone, String mobilePhone){
this(ID, name, gender);
this.residentAddress = residentAddress;
this.mailingAddress = mailingAddress;
this.email = email;
this.phone = phone;
}
}
我們可以從上面的定義看出,Person的建構子已經非常的冗長了。
除此之外,我們裡面有許多選項是選填的,例如電話、電子郵件等等,這些都會造成在建構建構子上有困難,
而這時我們就可以利用 Builder Pattern 來重新設計 Student 的建構子。
根據以上的程式,我們會這樣去建構每個人的資料:
Person personA = new Person("xxxxxxxxx", "小明", 0, "台北市XXXXXXXXX", "台北市XXXXXXXXX", "xxxx@gmail.com", "02-xxxxxx", "09xxxxxx" );
Person personB = new Person("xxxxxxxxx", "小王", 0, "高雄市XXXXXXX", "台中市XXXXXXX", null, "02-xxxxxx", null );
Person personC = new Person("xxxxxxxxx", "小美", 1, "新北市XXXXXXXXXXX", "桃園縣XXXXXXXXXXXX", null, null, null );
二、建立 Builder
我們先來看建立者類別的寫法:
class PersonBuilder{
private String ID; //身分字字號
private String name; //名稱
private int gender; //性別
private String residentAddress; //戶籍地址
private String mailingAddress; //通訊住址
private String email; //電子郵件
private String phone; //電話
private String mobilePhone; //手機
/** 建構子 1
* @param ID 身分證
* @param name 姓名 */
public PersonBuilder(String ID, String name){
this.ID = ID;
this.name = name;
}
/** 設定電話 */
public PersonBuilder setPhone( String phone ){
this.phone = phone;
return this;
}
/** 性別 */
public PersonBuilder setGender( int gender ){
this.gender = gender;
return this;
}
/** 設定電子郵件 */
public PersonBuilder setEmail( String email ){
this.email = email;
return this;
}
/** 設定戶籍地址 */
public PersonBuilder setResidentAddress( String residentAddress ){
this.residentAddress = residentAddress;
return this;
}
/** 設定通訊地址 */
public PersonBuilder setMailingAddress( String mailingAddress ){
this.mailingAddress = mailingAddress;
return this;
}
/** 與戶籍同地址 */
public PersonBuilder setSameAddress(){
this.mailingAddress = residentAddress;
return this;
}
/** 設定手機 */
public PersonBuilder setMobilePhone( String mobilePhone ){
this.mobilePhone = mobilePhone;
return this;
}
/** 建立 Person 物件 */
public Person build(){
return new Person(ID, name, gender, residentAddress, mailingAddress, email, phone, mobilePhone);
}
}
建立 Person 物件:
Person personA = new PersonBuilder("xxxxxxxx", "小明")
.setGender( 0 )
.setResidentAddress( "台北市XXXXXXXXX" )
.setSameAddress()
.setEmail( "xxxx@gmail.com")
.setPhone( "02-xxxxxx" )
.setMobilePhone( "09xxxxxx" )
.build();
Person personC = new PersonBuilder("xxxxxxxx", "小美")
.setGender( 1 )
.setResidentAddress( "台北市XXXXXXXXX" )
.setMailingAddress( "桃園縣XXXXXXXXXXXX" )
.build();
以這樣直接看起來,是否更容易閱讀了,能兼具程式的可讀性與彈性
,這個就是建立者模式的精隨所在。
三、結論
根據以上的程式範例,我們可以發現 建立者模式(Builder pattern) 的好處,
但是事實上也是有壞處的,我們可以分為以下幾點
好處:
- 可讀性高
- 具有彈性
- 也能在 Setter 裡設定參數檢查
- 能留 final 修飾詞在原本的 class 裡
缺點:
- 程式碼變的冗長
- 原本的 class 新增參數時,builder 也要做對應的新增
而在 Java 中的有些 Class 也有用到這種設計模式,例如:
我們在撰寫程式時,從簡單到複雜,而在這之中,當整體的類別變得複雜且龐大時,假如自己在使用或建構物件時
,時常參數定義錯誤或不完全時,就可以去試試看這個方法,雖然會犧牲一些效率與程式碼空間
,但是要創造出容易維護且彈性高的軟體這些代價是可以被接受的。畢竟我想大家在除錯時
,一定非常不喜歡看到一大坨長長的程式碼吧!當自己在填入參數時,早就看得眼花撩亂了,更何況是在除錯的環境下!