一询兴、文章前言
我們?cè)趈ava中穿梭時(shí)都會(huì)不停的構(gòu)建對(duì)象乃沙,new對(duì)象,但是為什么我卻找不到“對(duì)象”就像一個(gè)“野指針”,仔細(xì)想想最有可能的就是沒(méi)有通過(guò)最好的手段去構(gòu)建對(duì)象诗舰。下文將會(huì)為大家談?wù)勅绾问褂胋uilder去構(gòu)建一個(gè)對(duì)象警儒。(本文參考《Effective Java》)
二、為什么使用Builder模式
1眶根、傳統(tǒng)的創(chuàng)建對(duì)象可以使用構(gòu)造器創(chuàng)建蜀铲,但是當(dāng)我們調(diào)用構(gòu)造器時(shí)通常需要許多你不想要設(shè)置的參數(shù),但是又不得不為它們傳值汛闸。這個(gè)時(shí)候如果我們使用重疊構(gòu)造器可行蝙茶,但是當(dāng)有許多參數(shù)的時(shí)候,客戶端的代碼就會(huì)非常難寫(xiě)诸老,并且很難閱讀隆夯。
重疊構(gòu)造器代碼如下
public class BuilderPerson {
//必選參數(shù)
private final String name;
private final int age;
private final int height;
private final int weight;
//可選參數(shù)
private final boolean isMarraying;
private final boolean isHasChildren;
public BuilderPerson(String name, int age) {
this(name,age,0);
}
public BuilderPerson(String name, int age, int height) {
this(name,age,height,0);
}
public BuilderPerson(String name, int age, int height, int weight) {
this(name,age,height,weight,false);
}
public BuilderPerson(String name, int age, int height, int weight, boolean isMarraying) {
this(name, age,height,weight,isMarraying,false);
}
public BuilderPerson(String name, int age, int height, int weight, boolean isMarraying, boolean isHasChildren) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
this.isMarraying = isMarraying;
this.isHasChildren = isHasChildren;
}
}
2钳恕、當(dāng)遇到許多構(gòu)造器參數(shù)的時(shí)候,還有第二中代替的辦法蹄衷,即使用JavaBean模式忧额,在這種模式下,調(diào)用一個(gè)無(wú)參的構(gòu)造器來(lái)創(chuàng)建對(duì)象愧口,然后調(diào)用setter方法來(lái)設(shè)置每個(gè)必要的參數(shù)睦番,以及每個(gè)相關(guān)的可選參數(shù)。
JavaBean代碼如下
public class BuilderPerson {
//必選參數(shù)
private String name;
private int age;
private int height;
private int weight;
//可選參數(shù)
private boolean isMarraying;
private boolean isHasChildren;
public BuilderPerson() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setHeight(int height) {
this.height = height;
}
public void setWeight(int weight) {
this.weight = weight;
}
public void setMarraying(boolean marraying) {
isMarraying = marraying;
}
public void setHasChildren(boolean hasChildren) {
isHasChildren = hasChildren;
}
}
但是JavaBean模式自身有著嚴(yán)重的缺點(diǎn)耍属,會(huì)導(dǎo)致類(lèi)處于不一致(你new了Test類(lèi)的兩個(gè)實(shí)例托嚣,一個(gè)只set了A屬性,一個(gè)只設(shè)置了B屬性厚骗,這兩個(gè)實(shí)例不一致示启,你不能保證通過(guò)該類(lèi)的同一個(gè)構(gòu)造器保證構(gòu)造出來(lái)的對(duì)象是屬性相同的。)的狀態(tài)领舰。
這時(shí)就出現(xiàn)了第三種替代的方法既能像重疊構(gòu)造器那樣的安全性夫嗓,也能保證代碼的可讀性即Builder模式。
代碼如下
public static class Builder{
//必選參數(shù)
private String name;
private int age;
private int height;
private int weight;
//可選參數(shù)
private final boolean isMarraying;
private final boolean isHasChildren;
public Builder(boolean isMarraying, boolean isHasChildren) {
this.isMarraying = isMarraying;
this.isHasChildren = isHasChildren;
}
public Builder name(String name) {
name = name;
return this;
}
public Builder age(int age) {
age = age;
return this;
}
public Builder height(int height) {
height = height;
return this;
}
public Builder weight(int weight) {
weight = weight;
return this;
}
public BuilderPerson builderPerson() {
return new BuilderPerson(this);
}
}
}
調(diào)用如下
BuilderPerson person = new BuilderPerson.Builder(false,false).
name("張三").age(20).height(180).weight(120).buildPerson();
總結(jié)
簡(jiǎn)而言之冲秽,如果類(lèi)的構(gòu)造器或者靜態(tài)工廠中具有多個(gè)參數(shù)舍咖,設(shè)計(jì)這種類(lèi)時(shí),Builder模式就是種不錯(cuò)的選擇锉桑,特別是當(dāng)大多數(shù)參數(shù)都是可選的時(shí)候排霉,與使用傳統(tǒng)的重疊構(gòu)造器模式相比,使用Builder模式的客戶端代碼將更易于閱讀和編寫(xiě)民轴,構(gòu)建器也比JavaBeans更加安全郑诺。