定义

将一个复杂对象的构建与它对的表示进行分离,使得同样的构建过程可以创建不同的表示

作用

在用户不知道对象的建造过程和细节的情况下就可以创建复杂的对象。

例如:
工厂模式负责建造汽车,那么工厂就要知道所有建造汽车的细节。
建造者模式就相当于是一个用户,只需要知道需求,想买什么汽车(对象和类型),就可以直接得到汽车。不需要知道汽车的建造细节。

角色分析

java能用来跑模型吗 java可以建模吗_建造者

那我们用建房子在说:假设造房简化为如下步骤:
1.打基地 2.钢筋工程 3.铺电线 4.粉刷 等;
“如果”要盖一个房子,首先要找一个建筑公司或工程承包商(指挥者)。承包商指挥工人(具体建筑者)过来造房子(产品),最后验收。

代码实现

类的结构图

java能用来跑模型吗 java可以建模吗_System_02


首先是一个抽象的建造者,定义了建造的内容,相当于是图纸

package com.ycm.builder.demo1;
//抽象的建造者。方法
public abstract class Builder {

    abstract void buildA();//地基
    abstract void buildB();//钢筋工程
    abstract void buildC();//铺电线
    abstract void buildD();//粉刷


    //获得产品
    abstract Product getProduct();
}

具体的建造者,相当于工人,具体去建造,得到产品

package com.ycm.builder.demo1;

public class Worker extends Builder {

    private Product product;

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

    @Override
    void buildA() {
        product.setBuildA("地基");
        System.out.println("地基");
    }

    @Override
    void buildB() {
        product.setBuildB("钢筋工程");
        System.out.println("钢筋工程");
    }

    @Override
    void buildC() {
        product.setBuildC("铺电线");
        System.out.println("铺电线");
    }

    @Override
    void buildD() {
        product.setBuildD("粉刷");
        System.out.println("粉刷");
    }

    @Override
    Product getProduct() {
        return product;
    }
}

得到的产品

package com.ycm.builder.demo1;
//具体的产品
public class Product {

    private String buildA;
    private String buildB;
    private String buildC;
    private String buildD;


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


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


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


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

指挥者,指挥工人使用图纸去建造房子

package com.ycm.builder.demo1;
//指挥:核心,负责指挥构建一个工程,工程如何构建,由它决定
public class Director {

    public Product builder(Builder builder){
        builder.buildA();
        builder.buildB();
        builder.buildC();
        builder.buildD();
        return builder.getProduct();
    }
}

测试类

package com.ycm.builder.demo1;

public class Test {
    public static void main(String[] args) {
        Director director = new Director();
        Product builder = director.builder(new Worker());
        System.out.println(builder);
    }
}

结果

java能用来跑模型吗 java可以建模吗_ide_03

分析

上面这种方法是BUilder的常规写法,其中Director在整个模式中起着很大的作用,用于指挥具体的建造者如何生产出产品,向调用者返回具体生产好的产品

更好的简化写法

可以把Director和抽象建造者进行结合

通过静态内部类方式实现零件无序装配构建,这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无需改变具体的构造方式。就可以生产出不同复杂产品

比如:麦当劳的套餐,服务员(具体构建者)可以随意搭配任意几种产品(零件) 组成一款套餐(产品),然后出售给客户。比第一种方式少了指挥者,主要是因为第二种方式把指挥者交给用户来操作,使得产品的创建更加简单灵活。

代码实现:

package com.ycm.builder.demo2;

public abstract class Builder {
    abstract Builder builderA(String msg); //汉堡
    abstract Builder builderB(String msg); //可乐
    abstract Builder builderC(String msg); //薯条
    abstract Builder builderD(String msg);//甜点


    abstract Product getProduct();
}

定义的setter方法,如果有传入修改的值就改变,没有就使用默认的值,再将当前对象返回出去

package com.ycm.builder.demo2;

public class Worker extends Builder {

    private Product product;

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


    @Override
    Builder builderA(String msg) {
        product.setBuilderA(msg);
        return this;
    }

    @Override
    Builder builderB(String msg) {
        product.setBuilderB(msg);
        return this;
    }

    @Override
    Builder builderC(String msg) {
        product.setBuilderC(msg);
        return this;
    }

    @Override
    Builder builderD(String msg) {
        product.setBuilderD(msg);
        return this;
    }

    @Override
    Product getProduct() {
        return product;
    }
}
package com.ycm.builder.demo2;

public class Product {

    private  String BuilderA="汉堡";
    private  String BuilderB="可乐";
    private  String BuilderC="薯条";
    private  String BuilderD="甜点";

    public void setBuilderA(String builderA) {
        BuilderA = builderA;
    }

    public void setBuilderB(String builderB) {
        BuilderB = builderB;
    }

    public void setBuilderC(String builderC) {
        BuilderC = builderC;
    }

    public void setBuilderD(String builderD) {
        BuilderD = builderD;
    }

    @Override
    public String toString() {
        return "Product{" +
                "BuilderA='" + BuilderA + '\'' +
                ", BuilderB='" + BuilderB + '\'' +
                ", BuilderC='" + BuilderC + '\'' +
                ", BuilderD='" + BuilderD + '\'' +
                '}';
    }
}
package com.ycm.builder.demo2;

public class Test {
    public static void main(String[] args) {
        Worker worker = new Worker();
		//这里可以使用链式编程
        Product product = worker.builderA("雪碧").builderB("鸡腿")
                .getProduct();
        System.out.println(product);
    }
}

总结

优点

  1. 产品的构建和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。
  2. 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
  3. 具体的构建者类之间是相互独立的,这有利于系统的扩展。增加新的具体构建者无需修改原有类库的代码,符合开闭原则。

缺点

  1. 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  2. 如果产品的内部变化复杂,可能会导致需要定义很多具体的构造者来实现这种变化,导致系统变得很庞大。

应用场景

  1. 需要生产的产品对象有复杂的内部结构,这些产品对象具备共性;
  2. 隔离复杂对象的创建和使用,并使得使用的创建过程可以创建不同的产品。
  3. 适合于一个具有较多的零件(属性)的产品(对象)的创建过程。