前言

建造者模式又被称呼为生成器模式,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
建造者模式,是最后能够生产出一个完整的产品,而不是零件,例如KFC的一个套餐,生产一辆完整的汽车,建造一个高楼大厦等。

实现方式

归类后有两种实现方式

<mark>1.通过Client、Director、Builder和Product形成的建造者模式</mark>
这种方式例如建造一个高楼,首先要打地基,然后搭建钢筋水泥结构,设置房屋电线走向,对房屋外貌进行粉刷等等。需要走固定流程
<mark>2.通过静态内部类方式实现零件无序装配话构造</mark>
这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无需改变具体的构造方式。就可以生产出不同复杂产品。例如KFC的不同组合的套餐。

第一种方式

角色:

抽象建造者(builder):描述具体建造者的公共接口,一般用来定义建造细节的方法,并不涉及具体的对象部件的创建。

具体建造者(ConcreteBuilder):描述具体建造者,并实现抽象建造者公共接口。

指挥者(Director):调用具体建造者来创建复杂对象(产品)的各个部分,并按照一定顺序(流程)来建造复杂对象。

产品(Product):描述一个由一系列部件组成较为复杂的对象。

假设造房简化为如下步骤:(1)地基(2)钢筋工程(3)铺电线(4)粉刷

如果要盖一座房子,首先要找一个建筑公司或工程承包商(指挥者)。承包商指挥工人(具体建造者)过来造房子(产品),最后验收。

<mark>具体步骤:</mark>
1.创建抽象建造者定义造房步骤
2.创建工人具体实现造房步骤
3.创建承包商指挥工人施工
4.验收,检查是否建造完成

话不多说先上代码

抽象建造者:Builder.java

/** * Builder.java * 抽象建造者 */
abstract class Builder {
   
    //地基
    abstract void buildA();
    //钢筋工程
    abstract void buildB();
    //铺电线
    abstract void buildC();
    //粉刷
    abstract void buildD();
    //完工-获取产品
    abstract Product getProduct();
}

具体建造者(工人):ConcreteBuilder.java

/** * ConcreteBuilder.java * 具体建造者(工人) */
public class ConcreteBuilder extends Builder{
   
    private Product product;
    public ConcreteBuilder() {
   
        product = new Product();
    }
    @Override
    void buildA() {
   
        product.setBuildA("地基");
    }
    @Override
    void buildB() {
   
        product.setBuildB("钢筋工程");
    }
    @Override
    void buildC() {
   
        product.setBuildC("铺电线");
    }
    @Override
    void buildD() {
   
        product.setBuildD("粉刷");
    }
    @Override
    Product getProduct() {
   
        return product;
    }
}

产品(房子):Product.java

/** * Product.java * 产品(房子) */
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) {
   
        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 buildA+"\n"+buildB+"\n"+buildC+"\n"+buildD+"\n"+"房子验收完成";
        }
}

指挥者:Director.java

/** * Director.java * 指挥者 */
public class Director {
   
    //指挥工人按顺序造房
    public Product create(Builder builder) {
   
        builder.buildA();
        builder.buildB();
        builder.buildC();
        builder.buildD();
        return builder.getProduct();
    }
}

测试类:Test.java

/** * Test.java * 测试类 */
public class Test {
   
    public static void main(String[] args) {
   
        Director director = new Director();
        Product create = director.create(new ConcreteBuilder());
        System.out.println(create.toString());
    }
}

运行结果:

第二种方式

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

具体步骤:
1.建造抽象建造者定义麦当劳的产品(类别)
2.创建具体的建造者
3.创建套餐产品
3.创建服务员将各部件组合成套餐
代码:

抽象建造者:Builder.java

/** * Builder.java * 建造者 */
abstract class Builder {
   
    //汉堡
    abstract Builder bulidA(String mes);
    //饮料
    abstract Builder bulidB(String mes);
    //薯条
    abstract Builder bulidC(String mes);
    //甜品
    abstract Builder bulidD(String mes);
    //获取套餐
    abstract Product build();
}

产品:Product.java

/** * Product.java * 产品(麦当劳套餐) */
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) {
   
        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 buildA+"\n"+buildB+"\n"+buildC+"\n"+buildD+"\n"+"组成套餐";
        }
}

具体建造者:ConcreteBuilder.java

/** * ConcreteBuilder.java * 具体建造者(服务员) */
public class ConcreteBuilder extends Builder{
   
    private Product product;
    public ConcreteBuilder() {
   
        product = new Product();
    }

    @Override
    Product build() {
   
        return product;
    }

    @Override
    Builder bulidA(String mes) {
   
        product.setBuildA(mes);
        return this;
    }

    @Override
    Builder bulidB(String mes) {
   
        product.setBuildB(mes);
        return this;
    }

    @Override
    Builder bulidC(String mes) {
   
        product.setBuildC(mes);
        return this;
    }

    @Override
    Builder bulidD(String mes) {
   
        product.setBuildD(mes);
        return this;
    }
}

测试类:Test.java

/** * Test.java * 测试类 */
public class Test {
   
    public static void main(String[] args) {
   
         ConcreteBuilder concreteBuilder = new ConcreteBuilder();
         Product build = concreteBuilder
                .bulidA("牛肉煲")
// .bulidC("全家桶")
                .bulidD("冰淇淋")
                .build();
        System.out.println(build.toString());
    }
}

运行

第二种建造方式比较灵活,它没有规定套餐是什么样的,而是规定了套餐是由几个部分组成(分类),然后具体建造的单类产品是什么掌握着顾客的手中,也就是说顾客知道套餐是由汉堡、饮料、薯条、甜品四种组成,然后可以随意进行搭配。比如汉堡有牛肉煲、鸡肉堡,饮料有可乐、果汁,薯条有大份、中份、小份(这里把薯条换成小吃比较好),甜品有冰淇淋、蛋糕等。

猜想

我们知道抽象工厂是专门生产各种具体商品类的,可以做一系类商品,我们把这个揉和进来,就相当于麦当劳的菜单了,菜单上也是按照产品系列分类的,然后我们也可以创建专门生产各种套餐的工厂,那么顾客更加简便了,不需要自己挨个点,只需要点套餐A、B、C即可。

文章部分来源