前言
建造者模式即BUilder模式,看名字就可知是一種創(chuàng)建型模式瀑志。主要是解決
- 構(gòu)造方法中參數(shù)過多導(dǎo)致的可讀性較差的問題涩搓;
- 在初始化時不必將所有參數(shù)進行設(shè)置的情況(通常有默認(rèn)值)。
文中會舉例進行演示劈猪,通過例子能夠有一個更清晰的認(rèn)識昧甘。
場景描述
許多游戲在進入游戲時,第一步往往是讓我們選擇角色的外形战得,如眼睛顏色充边,眼睛大小,發(fā)型常侦,頭發(fā)顏色浇冰,臉型等等予弧。假設(shè)現(xiàn)在要創(chuàng)建一個小明,大眼湖饱,綠色的瞳孔掖蛤,中分頭,紅色頭發(fā)井厌,鞋拔子臉蚓庭。當(dāng)然還有必填的姓名。
首先仅仆,我們創(chuàng)建一個Person的類器赞,并改寫toString方法便于測試。
public class Person {
private String name;//姓名必填
private String eyeSize;//眼睛大小
private String eyeColor;//眼睛顏色
private String hairStyle;//發(fā)型
private String hairColor;//頭發(fā)顏色
private String face;//臉型
public Person(String name, String eyeSize, String eyeColor, String hairStyle, String hairColor, String face) {
this.name = name;
this.eyeSize = eyeSize;
this.eyeColor = eyeColor;
this.hairStyle = hairStyle;
this.hairColor = hairColor;
this.face = face;
}
@Override
public String toString() {
String s = "姓名:" + name + "\n"
+ "眼睛:" + eyeSize + "\n"
+ "眼睛顏色:" + eyeColor + "\n"
+ "發(fā)型:" + hairStyle + "\n"
+ "頭發(fā)顏色:" + hairColor + "\n"
+ "臉型:" + face;
return s;
}
}
同時我們編寫測試類墓拜,創(chuàng)建小明這個角色港柜。在創(chuàng)建時我郁悶了,在通過構(gòu)造方法對對象進行初始化時咳榜,我忘記了參數(shù)的順序夏醉。雖然現(xiàn)在IDE都非常的智能,會對參數(shù)進行提示涌韩,但是還是影響了我的開發(fā)效率畔柔。
最后我們艱辛的創(chuàng)建完了這個簡單的測試類
public static void main(String[] args) {
Person xiaoming = new Person("小明","大", "綠色", "中分", "紅色", "鞋拔子臉");
System.out.println(xiaoming.toString());
}
輸入結(jié)果如下:
姓名:小明
眼睛:大
眼睛顏色:綠色
發(fā)型:中分
頭發(fā)顏色:紅色
臉型:鞋拔子臉
老鐵,沒毛病臣樱。但是現(xiàn)在是只有6個參數(shù)的情況下靶擦,似乎還可以接受,但是如果再多幾個雇毫,orzP丁!
使用Builder模式
首先來說說使用Builder模式有什么優(yōu)點:
- 默認(rèn)參數(shù)棚放,無需對所有參數(shù)進行初始化枚粘;
- 將實現(xiàn)變成鏈?zhǔn)秸{(diào)用,增加了代碼可讀性席吴。
現(xiàn)在不管角色的外形赌结,我只想創(chuàng)建一個小明的對象,來看看Builder模式會怎么做:
public static void main(String[] args) {
Person xiaoming = new Person.Builder("小明").create();
System.out.println(xiaoming.toString());
}
Are you kidding孝冒?就傳了個必填項姓名就創(chuàng)建好了柬姚?僅用一行代碼就創(chuàng)建好了這個對象。
在前言中講到過一點庄涡,設(shè)置默認(rèn)值量承。以上實現(xiàn)就是基于默認(rèn)值的設(shè)置。
接下來就來到了緊張刺激的代碼實現(xiàn)環(huán)節(jié)。Builder的實現(xiàn)
public class Person {
private String name;//姓名必填
//省略其他可選參數(shù)
private Person(Builder builder) { //1............
initialize(builder);
}
private void initialize(final Builder builder) {
name = builder.name;
//省略
}
public static class Builder {
//2..........
private String name;//姓名必填
private String eyeSize = "大";//眼睛大小
//省略
public Builder(String name) {
this.name = name;
}
public Builder setEyeSize(String eyeSize) {
this.eyeSize = eyeSize;
//3..........
return this;
}
//省略
//4..........
public Person create() {
return new Person(this);
}
}
@Override
public String toString() {
String s = "姓名:" + name + "\n"
+ "眼睛:" + eyeSize + "\n"
+ "眼睛顏色:" + eyeColor + "\n"
+ "發(fā)型:" + hairStyle + "\n"
+ "頭發(fā)顏色:" + hairColor + "\n"
+ "臉型:" + face;
return s;
}
}
劃一下重點:
- 因為我們要用過Builder來創(chuàng)建對象撕捍,所有需將Person類的構(gòu)造方法私有化拿穴,且通過Builder來構(gòu)建;
- 在Builder中初始化變量,對外部提供set方法;
- 實現(xiàn)鏈?zhǔn)降年P(guān)鍵 return this;
- 設(shè)置完參數(shù)之后通過Person類的構(gòu)造進行構(gòu)建并返回實例對象忧风。
繼續(xù)創(chuàng)建一個好看點的小紅:
Person xiaohong = new Person.Builder("小紅")
.setEyeColor("藍(lán)色")
.setEyeSize("大")
.setFace("鵝蛋臉")
.setHairStyle("大波浪")
.setHairColor("褐色")
.create();
是不是格外的清晰默色。
總結(jié)
將代碼寫成鏈?zhǔn)绞欠浅?yōu)美的事情,像在Android開發(fā)中狮腿,我們可以將TitleBar的設(shè)置寫成鏈?zhǔn)酵仍祝部梢詫ecyclerView的初始化過程寫成鏈?zhǔn)剑?br> 看過dagger2生成的代碼就可以看出,文中builder模式是仿造它的實現(xiàn)缘厢,要是沒看過現(xiàn)在也可以轉(zhuǎn)去看吃度,相信會輕松許多;
完整代碼移步gayhub贴硫。