Separate the construction of a complex object from its representation so that the sameconstruction process can create different representations.java
將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。git
由多個部件組成設計模式
public class Product { private String partA; private String partB; public String getPartA() { return partA; } public void setPartA(String partA) { this.partA = partA; } public String getPartB() { return partB; } public void setPartB(String partB) { this.partB = partB; } @Override public String toString() { return "partA:" + partA + ", partB:" + partB; } } 複製代碼
規範產品的組建,通常是由子類實現。其中,buildPart方法是零件的配置,設置一個不一樣零件,或者不一樣的裝配順序就可能產生不一樣的產品。markdown
public abstract class Builder { /** * 設置產品的不一樣組件/零件,以得到不一樣的產品 */ public abstract void buildPartA(); /** * 設置產品的不一樣組件/零件,以得到不一樣的產品 */ public abstract void buildPartB(); /** * 建造產品 * @return */ public abstract Product getProduct(); } 複製代碼
實現抽象類定義的全部方法,而且返回一個組建好的對象ide
public class ConcreteBuilder1 extends Builder { private Product product = new Product(); @Override public void buildPartA() { System.out.println("ConcreteBuilder1->buildPartA()"); product.setPartA("組件A1"); } @Override public void buildPartB() { System.out.println("ConcreteBuilder1->buildPartB()"); product.setPartB("組件B1"); } @Override public Product getProduct() { System.out.println("ConcreteBuilder1->getProduct()"); return product; } } 複製代碼
public class ConcreteBuilder2 extends Builder { private Product product = new Product(); @Override public void buildPartA() { System.out.println("ConcreteBuilder2->buildPartA()"); product.setPartA("組件A2"); } @Override public void buildPartB() { System.out.println("ConcreteBuilder2->buildPartB()"); product.setPartB("組件B2"); } @Override public Product getProduct() { System.out.println("ConcreteBuilder2->getProduct()"); return product; } } 複製代碼
也叫指揮者類,負責安排已有模塊的順序,而後告訴Builder開始建造。導演類起到封裝的做用,避免高層模塊深刻到建造者內部的實現類。在建造者模式比較龐大時,導演類能夠有多個。oop
public class Director { private Builder builder; public Director(Builder builder){ this.builder = builder; } /** * 將部件partA、partB...最後組成複雜對象(使用多個簡單的對象一步一步構建成一個複雜的對象) */ public void construct(){ builder.buildPartA(); builder.buildPartB(); } } 複製代碼
public class Client { public static void main(String[] args) { Builder builder1 = new ConcreteBuilder1(); Director director1 = new Director(builder1); director1.construct(); Product product1 = builder1.getProduct(); System.out.println(product1); Builder builder2 = new ConcreteBuilder2(); Director director2 = new Director(builder2); director2.construct(); Product product2 = builder2.getProduct(); System.out.println(product2); } } 複製代碼
封裝性ui
客戶端沒必要知道產品內部組成的細節this
建造者獨立,容易擴展spa
便於控制細節風險設計
因爲具體的建造者是獨立的,所以能夠對建造過程逐步細化,而不對其餘的模塊產生任何影響
相同的方法,不一樣的執行順序,產生不一樣的事件結果時,能夠採用建造者模式。
多個部件或零件,均可以裝配到一個對象中,可是產生的運行結果又不相同時,則可使用該模式。
產品類很是複雜,或者產品類中的調用順序不一樣產生了不一樣的效能,這個時候使用建造者模式很是合適。
在對象建立過程當中會使用到系統中的一些其餘對象,這些對象在產品對象的建立過程當中不易獲得時,也能夠採用建造者模式封裝該對象的建立過程。
該種場景只能是一個補償方法,由於一個對象不容易得到,而在設計階段居然沒有發覺,而要經過建立者模式柔化建立過程,自己已經違反設計的最初目標。
除上面的通用源碼實現外,還有另一種更爲常見的場景,就是當一個類構造器須要傳入不少參數時,而且一般有一部分參數是可選的,若是使用構造方法建立這個類的實例,代碼可讀性會很是差,並且很容易引入錯誤,此時就能夠利用 builder模式:
public class Person { private final String cardId; private final String name; private final Integer age; private final String sex; private final String address; public static class Builder { // 必須的參數 private final String cardId; private final String name; // 可選的參數 private Integer age; private String sex; private String address; public Builder(String cardId, String name) { this.cardId = cardId; this.name = name; } public Builder age(Integer age) { this.age = age; return this; } public Builder sex(String sex) { this.sex = sex; return this; } public Builder address(String address) { this.address = address; return this; } public Person build() { return new Person(this); } } private Person(Builder builder) { this.cardId = builder.cardId; this.name = builder.name; this.age = builder.age; this.sex = builder.sex; this.address = builder.address; } @Override public String toString() { return "cardId:" + cardId + ",name:" + name + ",age:" + age + ",sex:" + sex + ",address:" + address; } } 複製代碼
public class Client { public static void main(String[] args) { Person zhangsan = new Person.Builder("100000000000000000", "張三") .age(28) .sex("MALE") .address("BJ") .build(); System.out.println(zhangsan); Person lisi = new Person.Builder("100000000000000001", "李四") .address("TJ") .build(); System.out.println(lisi); } } 複製代碼
上面的代碼經過Person的內部類Builder建立一個Person實例,其中,李四對年齡和性別進行了」保密「(age和sex均爲可選參數)。能夠看到,代碼看起來更爲優雅,大大加強了可讀性,而且客戶端代碼也更容易編寫。
參考文獻:《設計模式之禪》