1. 構(gòu)建器是什么疚顷?
構(gòu)建器也是一種獲得類對象的方法旱易,在前面我們介紹了通過 構(gòu)造器 與 靜態(tài)工廠方法 兩種方式來獲得類的對象。
這里我們寫一個(gè) Person 類荡含,并為這個(gè)類加上構(gòu)建器:
public class Person {
private final String name;
private final int age;
private final String address;
private final String phone;
public static class Builder{
private final String name;
private final int age;
private String address = null;
private String phone = null;
public Builder(String name,int age){
this.name = name;
this.age = age;
}
public Builder address(String val){
address = val;
return this;
}
public Builder phone(String val){
phone = val;
return this;
}
public Person builder(){
return new Person(this);
}
}
private Person(Builder builder){
this.name = builder.name;
this.age = builder.age;
this.address = builder.address;
this.phone = builder.phone;
}
@Override
public String toString() {
return "name:"+name+" age:"+age+" address:"+address+" phone:"+phone;
}
}
調(diào)用這個(gè)構(gòu)建器的方式
public class PersonTest {
public static void main(String[] args) {
Person p = new Person.Builder("tom", 18).address("深圳").phone("110").builder();
System.out.println(p.toString());
}
}
2.為什么使用構(gòu)建器咒唆?
2.1參數(shù)的限制
靜態(tài)工廠方法與構(gòu)造器都有一個(gè)共同的局限性,就是它們不能很好的擴(kuò)展到大量的可選參數(shù)释液。就像我們上面的那個(gè)Person 類全释,在實(shí)際中我們會(huì)有許多的屬性,性別误债、出生年月浸船、愛好...對與這樣的類。
2.2 重疊構(gòu)造器
我們初學(xué)的時(shí)候都會(huì)選擇 重疊構(gòu)造器(telecoping constructor)模式 寝蹈。在這種情況下李命,第一個(gè)構(gòu)造器是實(shí)例化對象必須的參數(shù),第二個(gè)會(huì)多一個(gè)參數(shù)箫老,就這樣疊加封字,最后是一個(gè)有所有參數(shù)的構(gòu)造器。
public class Person {
private final String name;
private final int age;
private final String address;
private final String phone;
public Person(String name, int age) {
this(name,age,null);
}
public Person(String name, int age, String address) {
this(name,age,address,null);
}
public Person(String name, int age, String address, String phone) {
super();
this.name = name;
this.age = age;
this.address = address;
this.phone = phone;
}
@Override
public String toString() {
return "name:"+name+" age:"+age+" address:"+address+" phone:"+phone;
}
}
獲得對象
public class PersonTest {
public static void main(String[] args) {
Person p = new Person("tom",18,null,"110");
System.out.println(p.toString());
}
}
在這個(gè)構(gòu)造器中也許會(huì)有你不想要的參數(shù)耍鬓,如果我們的參數(shù)變多了的話阔籽,情況就不會(huì)很好。
總結(jié)一句話:重疊構(gòu)造器可行牲蜀,但當(dāng)有很多的參數(shù)的時(shí)候笆制,客戶端的代碼就會(huì)很難編寫并且不容易閱讀我們在使用的時(shí)候,必須很仔細(xì)的看每一個(gè)參數(shù)的位置和含義涣达。
2.3 JavaBeans模式
2.3.1 創(chuàng)建JavaBeans模式
這個(gè)時(shí)候我們還有一種替代的方式在辆,這個(gè)就是JavaBeans模式证薇。這種種模式下,使用無參的構(gòu)造方法創(chuàng)建對象匆篓,然后調(diào)用setter 方法給屬性設(shè)置值
public class Person {
private String name;
private int age;
private String address;
private String phone;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setAddress(String address) {
this.address = address;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "name:"+name+" age:"+age+" address:"+address+" phone:"+phone;
}
}
使用的方式浑度,這個(gè)相比與重疊構(gòu)造器更容易的創(chuàng)建了對象,同時(shí)讓代碼跟容易的閱讀鸦概。
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.setName("tom");
p.setAge(18);
p.setAddress("深圳");
p.setPhone("110");
System.out.println(p.toString());
}
}
2.3.2 JavaBeans模式的劣勢
構(gòu)造的過程分到了幾個(gè)調(diào)用中俺泣,在構(gòu)造JavaBeans的時(shí)候可能會(huì)不一致
類無法僅僅通過檢驗(yàn)構(gòu)造器參數(shù)的有效性來保證一致性!
對象的不一致會(huì)導(dǎo)致失敗完残,JavaBeans模式阻止了把類做為不可變的可能,需要程序員做額外努力來保證它線程安全横漏。
2.4 構(gòu)建器
2.4.1構(gòu)建器的優(yōu)勢
構(gòu)建器的創(chuàng)建對象就比較易于創(chuàng)建與閱讀,線程安全
等待所有的參數(shù)驗(yàn)證通過才會(huì)build()對象谨设。
與構(gòu)造器相比,builder 的微略優(yōu)勢在缎浇,builder可以有多個(gè)可變(varargs)參數(shù)扎拣。構(gòu)造器像方法一樣,只有一個(gè)可變參數(shù)素跺。因?yàn)閎uilder利用單獨(dú)的方法來設(shè)置每個(gè)參數(shù)二蓝,你想要多少個(gè)可變參數(shù),他們就可以有多少個(gè)指厌,知道每個(gè)setter方法都有一個(gè)可變參數(shù)刊愚。
builder模式非常靈活,可以理由單個(gè)builder構(gòu)建多個(gè)對象踩验。builder的參數(shù)可以在創(chuàng)建對象時(shí)進(jìn)行調(diào)整
設(shè)置了參數(shù)的builder生成一個(gè)很好的抽象工廠(Abstract Factory),也就是客戶端可以將這樣一個(gè)builder傳給方法鸥诽,使該方法能為客戶端創(chuàng)建一個(gè)或者多個(gè)對象
2.4.1構(gòu)建器的劣勢
builder也有自己的不足,就是創(chuàng)建對象就必須創(chuàng)建它的構(gòu)建器箕憾。雖然創(chuàng)建構(gòu)建器的開銷在實(shí)踐中可能不是很明顯牡借。但在注意性能的情況下,這個(gè)就是問題了袭异。
builder模式還比重疊構(gòu)造器模式更加的冗長钠龙,因此它會(huì)在參數(shù)多的時(shí)候使用。但是我們?nèi)绻烙澹覀兛赡軙?huì)在設(shè)計(jì)之后還要添加參數(shù)碴里,所以已開始就用構(gòu)建器還是比較好的。
3 總結(jié)
如果類的構(gòu)造器或者靜態(tài)工廠中具有多個(gè)參數(shù)畅买,設(shè)計(jì)這種類時(shí)并闲,Builder模式就是不錯(cuò)的選擇,特別是當(dāng)大多數(shù)參數(shù)都是可選的時(shí)候谷羞。
與重疊構(gòu)造器相比帝火,builder模式的客戶端更易與閱讀和編寫
與JavaBeans相比溜徙,更加的安全