天天看點

23種設計模式——建造者模式23種設計模式——建造者模式

文章目錄

  • 23種設計模式——建造者模式
    • 1、建造者模式概述
    • 2、建造者模式的結構
    • 3、建造者模式的實作
      • 3.1、正常實作
      • 3.2、更為靈活的實作
    • 4、建造者模式和工廠模式的差別

23種設計模式——建造者模式

1、建造者模式概述

建造者(Builder)模式的定義:指将一個複雜對象的構造與它的表示分離,使同樣的建構過程可以建立不同的表示,這樣的設計模式被稱為建造者模式。它是将一個複雜的對象分解為多個簡單的對象,然後一步一步建構而成。它将變與不變相分離,即産品的組成部分是不變的,但每一部分是可以靈活選擇的。

該模式的主要優缺點如下:

  1. 封裝性好,建構和表示分離。
  2. 擴充性好,各個具體的建造者互相獨立,有利于系統的解耦。
  3. 用戶端不必知道産品内部組成的細節,建造者可以對建立過程逐漸細化,而不對其它子產品産生任何影響,便于控制細節風險。

其缺點如下:

  1. 産品的組成部分必須相同,這限制了其使用範圍。
  2. 如果産品的内部變化複雜,如果産品内部發生變化,則建造者也要同步修改,後期維護成本較大。

建造者(Builder)模式和工廠模式的關注點不同:建造者模式注重零部件的組裝過程,而工廠方法模式更注重零部件的建立過程,但兩者可以結合使用。

應用場景:

  • 相同的方法,不同的執行順序,産生不同的結果。
  • 多個部件或零件,都可以裝配到一個對象中,但是産生的結果又不相同。
  • 産品類非常複雜,或者産品類中不同的調用順序産生不同的作用。
  • 初始化一個對象特别複雜,參數多,而且很多參數都具有預設值。

2、建造者模式的結構

建造者(Builder)模式的主要角色如下。

  1. 産品角色(Product):它是包含多個組成部件的複雜對象,由具體建造者來建立其各個零部件。
  2. 抽象建造者(Builder):它是一個包含建立産品各個子部件的抽象方法的接口/抽象類,通常還包含一個傳回複雜産品的方法 getResult()。
  3. 具體建造者(Concrete Builder):實作 Builder 接口,完成複雜産品的各個部件的具體建立方法。
  4. 指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成複雜對象的建立,在指揮者中不涉及具體産品的資訊。

建造者模式的結構圖:

23種設計模式——建造者模式23種設計模式——建造者模式

3、建造者模式的實作

3.1、正常實作

具體的産品類,包含多個組成部件

public class Product {

    //有ABCD多個部件
    private String buildA;
    private String buildB;
    private String buildC;
    private String buildD;

    public String getBuildA() {
        return buildA;
    }

    public void setBuildA(String buildA) {
        this.buildA = buildA;
    }

    public String getBuildB() {
        return buildB;
    }

    public void setBuildB(String buildB) {
        this.buildB = buildB;
    }

    public String getBuildC() {
        return buildC;
    }

    public void setBuildC(String buildC) {
        this.buildC = buildC;
    }

    public String getBuildD() {
        return buildD;
    }

    public void setBuildD(String buildD) {
        this.buildD = buildD;
    }

    @Override
    public String toString() {
        return "Product{" +
                "buildA='" + buildA + '\'' +
                ", buildB='" + buildB + '\'' +
                ", buildC='" + buildC + '\'' +
                ", buildD='" + buildD + '\'' +
                '}';
    }
}
           

抽象建造者,包含建立産品各個子部件的抽象方法

//抽象的建造者
public abstract class Builder {

    //具體産品的各個子部件的抽象方法
    abstract void buildA();//部件A
    abstract void buildB();//部件B
    abstract void buildC();//部件C
    abstract void buildD();//部件B

    //傳回具體産品的方法
    abstract Product getProduct();


}
           

具體建造者1,實作 Builder 接口,完成複雜産品的各個部件的具體建立方法。

//具體建造者,實作抽象建造者,完成複雜産品的各個部件的具體建立方法
public class Worker extends Builder{

   private Product product;  //提升作用域

   //通過具體建造者的構造器生成具體産品的對象
   public Worker(){
       product = new Product();
   }

    @Override
    void buildA() {
        product.setBuildA("完成部件A");
        System.out.println("完成部件A");
    }

    @Override
    void buildB() {
        product.setBuildB("完成部件B");
        System.out.println("完成部件B");
    }

    @Override
    void buildC() {
        product.setBuildC("完成部件C");
        System.out.println("完成部件C");
    }

    @Override
    void buildD() {
        product.setBuildD("完成部件D");
        System.out.println("完成部件D");
    }

    @Override
    Product getProduct() {
        System.out.println("完成産品ABCD的建立");
        return product;
    }
}
           

具體建造者2,實作 Builder 接口,完成複雜産品的各個部件的具體建立方法。

public class WorkerTwo extends Builder{

    private Product product;

    public WorkerTwo(){
        product = new Product();
    }

    @Override
    void buildA() {
        product.setBuildA("完成部件A2");
        System.out.println("完成部件A2");
    }

    @Override
    void buildB() {
        product.setBuildB("完成部件B2");
        System.out.println("完成部件B2");

    }

    @Override
    void buildC() {
        product.setBuildC("完成部件C2");
        System.out.println("完成部件C2");

    }

    @Override
    void buildD() {
        product.setBuildD("完成部件D2");
        System.out.println("完成部件D2");

    }

    @Override
    Product getProduct() {
        System.out.println("完成産品ABCDTWO的建立");
        return product;
    }
}
           

指揮者,調用建造者對象中的部件構造與裝配方法完成複雜對象的建立

public class Director {

    //調用建造者對象中的部件構造與裝配方法完成複雜對象的建立
    public Product construct(Builder builder){
        builder.buildA();
        builder.buildB();
        builder.buildC();
        builder.buildD();

        return builder.getProduct();
    }
}
           

客戶類,實作具體建造者1

public class Client {
    public static void main(String[] args) {

        Director director = new Director();
        Product build = director.construct(new Worker());//實作具體建造者1
        System.out.println(build.toString());
    }
}
           

測試:

23種設計模式——建造者模式23種設計模式——建造者模式

客戶類,實作具體建造者2

public class Client {
    public static void main(String[] args) {

        Director director = new Director();
        Product build = director.construct(new WorkerTwo());
        System.out.println(build.toString());
    }
}
           

測試:

23種設計模式——建造者模式23種設計模式——建造者模式
上面示例是 Builder模式的正常用法,指揮者類 Director 在 Builder模式中具有很重要的作用,它用于指導具體建構者如何建構産品,控制調用先後次序,并向調用者傳回完整的産品類,但是有些情況下需要簡化系統結構,可以把Director和抽象建造者進行結合。

3.2、更為靈活的實作

産品–>套餐

public class Product {
    //預設套餐
    private String BuildA = "漢堡";
    private String BuildB = "薯條";
    private String BuildC = "炸雞";
    private String BuildD = "可樂";

    public String getBuildA() {
        return BuildA;
    }

    public void setBuildA(String buildA) {
        BuildA = buildA;
    }

    public String getBuildB() {
        return BuildB;
    }

    public void setBuildB(String buildB) {
        BuildB = buildB;
    }

    public String getBuildC() {
        return BuildC;
    }

    public void setBuildC(String buildC) {
        BuildC = buildC;
    }

    public String getBuildD() {
        return BuildD;
    }

    public void setBuildD(String buildD) {
        BuildD = buildD;
    }

    @Override
    public String toString() {
        return "Product{" +
                "BuildA='" + BuildA + '\'' +
                ", BuildB='" + BuildB + '\'' +
                ", BuildC='" + BuildC + '\'' +
                ", BuildD='" + BuildD + '\'' +
                '}';
    }
}
           

抽象建造類

public abstract class Builder {

    abstract Builder buildA(String msg);//漢堡
    abstract Builder buildB(String msg);//薯條
    abstract Builder buildC(String msg);//炸雞
    abstract Builder buildD(String msg);//可樂

    //傳回具體的套餐
    abstract Product getProduct();
}
           

具體建造者–>服務員

public class Worker extends Builder{

    private Product product;

    public Worker() {
        product = new Product();
    }

    @Override
    Builder buildA(String msg) {
        product.setBuildA(msg);
        return this;
    }

    @Override
    Builder buildB(String msg) {
        product.setBuildB(msg);
        return this;
    }

    @Override
    Builder buildC(String msg) {
        product.setBuildC(msg);
        return this;
    }

    @Override
    Builder buildD(String msg) {
        product.setBuildD(msg);
        return this;
    }

    @Override
    Product getProduct() {
        return product;
    }


}
           

客戶:實作預設套餐

public class Client {
    public static void main(String[] args) {
        Worker worker = new Worker();
        Product product = worker.getProduct();
        System.out.println(product.toString());
    }
}
           

測試:

23種設計模式——建造者模式23種設計模式——建造者模式

實作自選套餐:

public class Client {
    public static void main(String[] args) {
        Worker worker = new Worker();
        Product product = worker
                .buildA("蛋糕")
                .buildB("雞腿")
                .buildC("")
                .buildD("")
                .getProduct();
        System.out.println(product.toString());
    }
}
           

測試:

23種設計模式——建造者模式23種設計模式——建造者模式

4、建造者模式和工廠模式的差別

  • 建造者模式更加注重方法的調用順序,工廠模式注重建立對象。
  • 建立對象的力度不同,建造者模式建立複雜的對象,由各種複雜的部件組成,工廠模式建立出來的對象都一樣
  • 關注重點不一樣,工廠模式隻需要把對象建立出來就可以了,而建造者模式不僅要建立出對象,還要知道對象由哪些部件組成。
  • 建造者模式根據建造過程中的順序不一樣,最終對象部件組成也不一樣。