建立型模式-建造者模式(複雜對象的組裝與建立)

1. 定義

建造者模式(Builder Pattern):將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。建造者模式是一種對象建立型模式。git

2. 結構

建造者模式一步一步建立一個複雜的對象,它容許用戶只經過指定複雜對象的類型和內容就能夠構建它們,用戶不須要知道內部的具體構建細節。建造者模式結構如圖所示:編程

建造者模式

在建造者模式結構圖中包含以下幾個角色:設計模式

  • Builder(抽象建造者):它爲建立一個產品Product對象的各個部件指定抽象接口,在該接口中通常聲明兩類方法,一類方法是buildPartX(),它們用於建立複雜對象的各個部件;另外一類方法是getResult(),它們用於返回複雜對象。Builder既能夠是抽象類,也能夠是接口。
  • ConcreteBuilder(具體建造者):它實現了Builder接口,實現各個部件的具體構造和裝配方法,定義並明確它所建立的複雜對象,也能夠提供一個方法返回建立好的複雜產品對象。
  • Product(產品角色):它是被構建的複雜對象,包含多個組成部件,具體建造者建立該產品的內部表示並定義它的裝配過程。
  • Director(指揮者):指揮者又稱爲導演類,它負責安排複雜對象的建造次序,指揮者與抽象建造者之間存在關聯關係,能夠在其construct()建造方法中調用建造者對象的部件構造與裝配方法,完成複雜對象的建造。客戶端通常只須要與指揮者進行交互,在客戶端肯定具體建造者的類型,並實例化具體建造者對象(也能夠經過配置文件和反射機制),而後經過指揮者類的構造函數或者Setter方法將該對象傳入指揮者類中。

3. 代碼實現

Productide

public class Product {

    private String partA;

    private String partB;

    private String partC;

    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;
    }

    public String getPartC() {
        return partC;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }
    
    @Override
    public String toString() {
        return "Product{" + "partA='" + partA + '\'' + ", partB='" + partB + '\'' + ", partC='" + partC + '\'' + '}';
    }
}

Builder函數

public abstract class Builder {

    protected Product product = new Product();

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    public Product getResult() {
        return product;
    }
}

ConcreteBuilderui

public class ConcreteBuilder extends Builder {

    @Override
    public void buildPartA() {
        product.setPartA("hahaA");
    }

    @Override
    public void buildPartB() {
        product.setPartB("hahaB");
    }

    @Override
    public void buildPartC() {
        product.setPartC("hahaC");
    }
}

Directorthis

public class Director {

    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}

Test設計

public class Test {

    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product product = director.construct();
        System.out.println(product);
    }
}

//Product{partA='hahaA', partB='hahaB', partC='hahaC'}

在建造者模式中,客戶端只需實例化指揮者類,指揮者類針對抽象建造者編程,客戶端根據須要傳入具體的建造者類型(可根據配置文件得到),指揮者將指導具體建造者一步一步構造一個完整的產品(逐步調用具體建造者的buildX()方法),相同的構造過程能夠建立徹底不一樣的產品。在遊戲角色實例中,若是須要更換角色,只須要修改配置文件,更換具體角色建造者類便可;若是須要增長新角色,能夠增長一個新的具體角色建造者類做爲抽象角色建造者的子類,再修改配置文件便可,原有代碼無須修改,徹底符合「開閉原則」。code

4. 省略Director與鉤子方法

1 省略Director,直接將Director中的construct方法放入Builer

public abstract class Builder {

    protected Product product = new Product();

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    public Product createProduct() {
        return product;
    }

    public Product construct() {
        this.buildPartA();
        this.buildPartB();
        this.buildPartC();
        return product;
    }
}


...
Builder builder = new ConcreteBuilder();
Product product=builder.construct();
...

2 添加鉤子方法來控制是否對某個buildX()進行調用

抽象類中給一個默認的鉤子方法

public abstract class Builder {

    protected Product product = new Product();

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    public Product createProduct() {
        return product;
    }
    //鉤子方法
    public boolean isCNeed(){
        return false;
    }

具體類中重寫鉤子方法

public class ConcreteBuilder extends Builder {
    ...
    
    @Override
    public boolean isCNeed() {
         return true;
    }
}

控制器根據鉤子方法來判斷某一個buildX()是否執行

public class Director {

    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        if(builder.isCNeed()){
            builder.buildPartC();
        }
        builder.buildPartC();
        return builder.createProduct();
    }
}

5. 優缺點

  • 優勢
  1. 產品的自己與產品的建立解耦,相同的建立過程能夠建立不一樣的對象。
  2. 每個具體建造者都相對獨立,而與其餘的具體建造者無關,所以能夠很方便地替換具體建造者或增長新的具體建造者,符合「開閉原則」。
  3. 能夠更加精細地控制產品的建立過程。
  • 缺點
  1. 建造者模式所建立的產品通常具備較多的共同點,其組成部分類似,若是產品之間的差別性很大,例如不少組成部分都不相同,不適合使用建造者模式,所以其使用範圍受到必定的限制。
  2. 若是產品的內部變化複雜,可能會致使須要定義不少具體建造者類來實現這種變化,致使系統變得很龐大,增長系統的理解難度和運行成本。

6. 適用場景

  1. 須要生成的產品對象有複雜的內部結構,這些產品對象一般包含多個成員屬性。
  2. 須要生成的產品對象的屬性相互依賴,須要指定其生成順序
  3. 對象的建立過程獨立於建立該對象的類。在建造者模式中經過引入了指揮者類,將建立過程封裝在指揮者類中,而不在建造者類和客戶類中。
  4. 隔離複雜對象的建立和使用,並使得相同的建立過程能夠建立不一樣的產品。

7. 我的理解

將複雜對象的建立過程給封裝了起來,同時將對象的建立過程與對象自己隔離開了,可以使用相同的建立過程來建立不一樣的產品對象(提供不一樣的Builder實現類便可)

參考

  1. Java設計模式-劉偉
相關文章
相關標籤/搜索