建造者模式

建造者模式也属于创建型模式它提供了一种创建对象的最佳方式。

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

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

用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)

工厂(建造者模式)∶负责制造汽车(组装过程和细节在内)

汽车购买者(用户)∶你只需要说出你需要的型号(对象的类型和内容),然后直接购买就可以使用了(不需要知道汽车是怎么组装的(车轮、车门、发动机、方向盘等等)

举例

假设造房简化为如下步骤:

  1. 地基

  2. 钢筋工程

  3. 铺电线

  4. 粉刷

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

指挥者指挥步骤

Builder抽象类

public abstract class Builder {
    abstract void buildA();//地基
    abstract void buildB();//钢筋工程
    abstract void buildC();//铺电线
    abstract void buildD();//粉刷
    //得到产品
    abstract Product getProduct();
}

工人继承了抽象类并且自行构建产品

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.setBuildB("粉刷");
        System.out.println("粉刷");
    }

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

指挥者只需要控制执行顺序即可

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

测试,new一个指挥者,给指挥者工人

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

产品实体product;制造图纸(抽象封装制造方法)builder;操作者具体实现(继承图纸,具体实现)worker;指挥官(封装调用执行者)director

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

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

用户不传,就是默认的汉堡可乐薯条甜点

Bulide(图纸)

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

实现者

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

产品有默认值,相当于套餐就在那里

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

    public String getBuilderA() {
        return BuilderA;
    }

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

    public String getBuilderB() {
        return BuilderB;
    }

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

    public String getBuilderC() {
        return BuilderC;
    }

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

    public String getBuilderD() {
        return BuilderD;
    }

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

    @Override
    public String toString() {
        return "Product{" +
                "BuilderA='" + BuilderA + '\'' +
                ", BuilderB='" + BuilderB + '\'' +
                ", BuilderC='" + BuilderC + '\'' +
                ", BuilderD='" + BuilderD + '\'' +
                '}';
    }
}

测试

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

image-20220925175251677

顺序交给顾客,自由组合套餐

image-20220925175413374

优点

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

缺点

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

应用场景

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

建造者与抽象工厂模式的比较:

  • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
  • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
  • 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车!

Q.E.D.


春风亦有春风愁,不劳春风为我忧