動機
格式轉換器,將一種格式轉換成多種格式
結構
參與者
Builder抽象類,多態調用:爲創建一個Product對象的各個部件指定抽象接口
ConcreteBuilder:不同技藝的工人
- 實現Builder的接口以構造和裝配該產品的各個部件
- 定義並明確它所創建的表示
- 提供一個檢索產品的接口
Director:負責人
構建一個使用Builder接口的對象
Product
- 表示被構造的複雜對象。ConcreteBuilder創建該產品的內部表示並定義它的裝配過程。
- 包含定義組成部件的類,包括將這些部件裝配成最終產品的接口
工頭來協調各個工人部件合作創建一所房子
僞代碼如下:
public class FangZi {//產品
private String type;
private String amt;
get/set
}
public abstract class Builder{//生產者規範
public abstract void work();
public abstract void shouFei();
}
public class PingFangBuilder extend Builder{//生產者1
FangZi pingFang = new FangZi();
public void work() {//生產過程1
System.out.println("創建了平房");
pingFang.setType("平房");
}
public void shouFei(){//生產過程2
System.out.println("平房收費100");
pingFang.setType("100");
}
public FangZi getResult() {//產品輸出
return FangZi;
}
}
public class BieShuBuilder extend Builder{//生產者2
FangZi pingFang = new FangZi();
public void work() {//生產過程1
System.out.println("創建了別墅");
pingFang.setType("平房");
}
public void shouFei(){//生產過程2
System.out.println("別墅收費1W");
pingFang.setType("1W");
}
public FangZi getResult() {//產品輸出
return FangZi;
}
}
public class Director{//負責人
private Builder builder;
public Director(Builder builder) {//接收需求
this.builder = builder;
}
//調配工作
public void construct(){//感覺可以放在構造器中,但是太隱形了並且不符合邏輯順序
builder.work();
builder.shouFei();
}
}
public class ClientUsr{//具體使用者
public static void main(String[] args) {
if(args[0] == 0) {
PingFangBuilder pingFangBu = new PingFangBuilder();
Director director = new Director(pingFangBu);
director.construct();
FangZi fangzi = pingFangBu.getResult();
}else {
BieShuBuilder pingFangBu = new BieShuBuilder();
Director director = new Director(pingFangBu);
director.construct();
FangZi fangzi = pingFangBu.getResult();
}
}
}
有疑問的地方:
- 爲什麼不在Director的構造器中實現construct()方法的功能,這樣更便捷、更隱形;而且防止了客戶端程序員忘記的可能風險
- 爲什麼不將getResult()放入Builder類中成爲抽象方法,這樣多態也可以產生,而且對於最後的客戶端代碼減少重複部分
協作
- 客戶創建Director對象,並用它所想要的Builder對象進行配置
- 一旦產品部件被生成,導向器就會通知生成器
- 生成器處理導向器的請求,並將部件添加到該產品中
- 客戶從生成器中檢索產品
意圖
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
適用性
- 當創建複雜對象的算法應該獨立於該對象的組成部分以及他們的裝配方式時。
- 當構造過程必須允許被構造的對象有不同的表示時
優缺點
- 可以改變一個產品的內部表示;Builder對象提供給導向器一個構造產品的抽象接口。該接口使得生成器可以隱藏這個產品的表示和內部機構。它同時也隱藏了該產品時如何裝配的。因爲產品時通過抽象接口構造的,你在改變該產品的內部表示時所要做的只是定義一個新的生成器。
- 將構造代碼和表示代碼分開;Builder模式通過封裝一個複雜對象的創建和表示方式提高了對象的模塊性。客戶不需要知道定義產品內部結構的類的所有信息;這些類是不出現在Builder接口中的。每個ConcreteBuilder包含了創建和裝配一個特定產品的所有代碼。這些代碼只需要寫一次;然後不同的Director可以複用它以在相同部件集合的基礎上構作不同的Product
- 對構造過程進行更精細的控制 Builder模式與一下子就生成產品的創建型模式不同,他是在導向者的控制下一步一步構造產品的。僅當該產品完成時導向者才從生成器中取回他。因爲Builder接口相比其他創建型模式能更好的反映產品的構造過程。這使你可以更精細的控制構建過程,從而能更精細的控制所得產品的內部結構。
實現
通常由一個抽象的Builder類爲導向者可能要求創建的每一個構件定義一個操作。這些操作缺省情況下什麼都不做。一個ConcreteBuilder類對它由興趣創建的構件重定義這些操作
相關模式
Abstract Factory與Builder相似,因爲它也可以創建複雜對象,主要區別是Builder模式着重於一步步構造一個複雜對象。而Abstract Factory着重於多個系列的產品對象(簡單的或是複雜的)。Builder在最後的一步返回產品,而對於Abstract Factory來說,產品是立即返回的。
總結
區別
Abstract Factory就是去一家炒菜館點菜,你可以點一個個的產品,點個西紅柿炒雞蛋
Builder是去美食城的蓋澆飯點菜,你可以選一葷兩素、兩葷一素,一個個的選擇部件,而不能讓廚師直接製作
兩種模式其實作用類似,可以實現的功能類似,區別是一個是多個產品,一個是一個產品的多個步驟