業務場景
在業務代碼中構造了一個類,裡面有7個字段,需要給構造方法傳7個值
public class Home {
//門
private String Door;
//椅子
private String Chair;
//廚房
private String Kitchen;
//馬桶
private String Toilet;
//浴室
private String Bathroom;
//書房
private String Study;
//遊泳池
private String SwimmingPoor;
public void setDoor(String door) {
Door = door;
}
public void setChair(String chair) {
Chair = chair;
}
public void setKitchen(String kitchen) {
Kitchen = kitchen;
}
public void setToilet(String toilet) {
Toilet = toilet;
}
public void setBathroom(String bathroom) {
Bathroom = bathroom;
}
public void setStudy(String study) {
Study = study;
}
public void setSwimmingPoor(String swimmingPoor) {
SwimmingPoor = swimmingPoor;
}
public Home(String door, String chair, String kitchen, String toilet, String bathroom, String study, String swimmingPoor) {
Door = door;
Chair = chair;
Kitchen = kitchen;
Toilet = toilet;
Bathroom = bathroom;
Study = study;
SwimmingPoor = swimmingPoor;
}
public Home() {
}
}
因為需要建房子,當時我們的類後面經過擴充發展到了15個字段,甚至更多
private String Door;//門
private String Chair; //椅子
private String Kitchen; //廚房
private String Toilet; //馬桶
private String Bathroom; //浴室
private String Study; //書房
private String SwimmingPoor; //遊泳池
.........
那繼續沿用現在的設計思路,構造函數的參數清單會變得很長,代碼在可讀性和易用性上都會變差。在使用構造函數的時候,我們就容易搞錯各參數的順序,傳遞進錯誤的參數值,導緻非常隐蔽的 bug。
Home home=new Home("鐵門","搖搖椅","廚房","","",......)
于是乎可能想到使用set方法來解決,可以選擇填寫或者不填寫
Home home=new Home();
home.setBathroom("玻璃浴室");
home.setChair("木椅子");
home.setDoor("防盜門");
home.setStudy("書房");
home.setToilet("");
home.set....
但問題又來了,如果我們的構造方法需要進行擴充,比如建有的類型的房子,有的參數不需要使用了,又編寫新的構造方法,一個參數依賴另外兩個參數,比如我設定了房間的大小,長寬這兩個屬性是互相依賴的。
public Home(String door, String chair, String kitchen,String width,String height)
{
Door = door;
Chair = chair;
Kitchen = kitchen;
Width=width;
Height=height;
}
這樣很好,可是如果我們參數就是随意更改和搭配的,那麼每次都需要我重新編寫構造參數,這樣還将細節對外暴露了。單純用構造函數或者set方法無法做到對參數進行限制,對象可能還存在空或者無效。
建造者模式重構
例如上面,有很多參數需要我們去搭配修改,用來建立不同的對象方法
就像建房子,我們不需要去建,隻需要把我們的需求告訴建造者,讓它去建立,最後我隻管得到這個房子去驗收。
建造者接口
public interface IHome {
IHome Door(String door);//桌子
IHome Chair(String chair); //椅子
IHome Kitchen(String kitchen); //廚房
IHome Toilet(String toilet); //馬桶
IHome Bathroom(String bathroom); //浴室
String getDetail();//詳細資訊
}
具體實作的建造者
public class HomeBuilder implements IHome {
Home home=new Home();
List<String> list=new ArrayList<>();
@Override
public IHome Door(String door) {
home.setDoor(door);
list.add(door);
return this;
}
@Override
public IHome Chair(String chair) {
home.setChair(chair);
list.add(chair);
return this;
}
@Override
public IHome Kitchen(String kitchen) {
home.setKitchen(kitchen);
list.add(kitchen);
return this;
}
@Override
public IHome Toilet(String toilet) {
home.setToilet(toilet);
list.add(toilet);
return this;
}
@Override
public IHome Bathroom(String bathroom) {
home.setBathroom(bathroom);
list.add(bathroom);
return this;
}
@Override
public String getDetail() {
StringBuilder detail = new StringBuilder();
for (String s : list) {
detail.append(s+" ");
}
return detail.toString();
}
}
建造者方法
public class Build {
//普通出租房
public IHome leveZero() {
return new HomeBuilder().Chair("塑膠椅").Door("塑膠門").Kitchen("小廚房");
}
//紅木家庭房子
public IHome leveOne() {
return new HomeBuilder().Chair("紅木椅").Bathroom("浴室").Door("紅木門");
}
//歐式家庭房子
public IHome leveTwo() {
return new HomeBuilder().Chair("北歐ins椅").Bathroom("露天浴室").Door("北歐ins門").Kitchen("北歐廚房");
}
}
測試驗證
public void test()
{
Build build=new Build();
String detail = build.leveOne().getDetail();
System.out.println(detail);
String detail2 = build.leveZero().getDetail();
System.out.println(detail2);
}

不同的家具、房間構成了不同的房子,如果将來業務擴充改動影響也不大
總結
一些基本東西不會變,而其組合經常變化的時候,就适合用建造者模式,特别是很多字段,很多種組合的時候,這種設計結構模型可以把重複的内容抽象
工廠模式和建造者模式的差別
工廠模式是用來建立不同但是相關類型的對象(繼承同一父類或者接口的一組子類),由給定的參數來決定建立哪種類型的對象。建造者模式是用來建立一種類型的複雜對 象,通過設定不同的可選參數,“定制化”地建立不同的對象。