Skip to content

【设计模式】-生成器模式

1074字约4分钟

java基础

2020-03-19

建造者模式、Builder

生成器模式 也叫建造者模式,可以理解成可以分步骤创建一个复杂的对象。在该模式中允许你使用相同的创建代码生成不同类型和形式的对象。

生成器的结构模式

  1. **生成器(Builder)**接口声明在所有类型生成器中通用的产品构造的步骤
  2. **具体的生成器(ConcreteBuilders)**提供构造过程的不同实现。 具体生成器也可以构造不遵循通用接口的产品。
  3. 产品 (Products) 是最终生成的对象。 由不同生成器构造的产品无需属于同一类层次结构或接口。
  4. 主管 (Director) 类定义调用构造步骤的顺序, 这样你就可以创建和复用特定的产品配置。
  5. 客户端 (Client) 必须将某个生成器对象与主管类关联。 一般情况下, 你只需通过主管类构造函数的参数进行一次性关联即可。 此后主管类就能使用生成器对象完成后续所有的构造任务。 但在客户端将生成器对象传递给主管类制造方法时还有另一种方式。 在这种情况下, 你在使用主管类生产产品时每次都可以使用不同的生成器。

案例分析

下面我们将结合一辆汽车的制造过程来模拟一个构建构成。针对汽车这种非常复杂的机械结构,我们需要将汽车各个零部件的组装过程抽取到不同的代码中,最终组成一个完成的产品。下面我们将简化这个过程,模拟一辆汽车的车型产品,命名,颜色喷漆,产品定价等信息。

核心类解释

  • 抽象出一个汽车产品Car
  • 定义Builder接口,规定Car的构建步骤和过程。
  • CarBuilder实现类。
  • CarDirectror统一构建过程。

代码实现

Car.class

public class Car {
    /**
     * 车型 SUV MVP 轿车等
     */
    private String type;
    /**
     * 汽车颜色
     */
    private String color;
    /**
     * 奥迪 啥的
     */
    private String name;
    /**
     * 售价
     */
    private BigDecimal price;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "type='" + type + '\'' +
                ", color='" + color + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

Builder.class

public interface Builder {
    /**
     * 定义车型
     * @param type
     * @return
     */
    Builder buildType(String type);

    /**
     * 定义产品名称
     * @param name
     * @return
     */
    Builder buildName(String name);

    /**
     * 确定颜色喷漆
     * @param color
     * @return
     */
    Builder buildColor(String color);

    /**
     * 定价
     * @param bigDecimal
     * @return
     */
    Builder buildPrice(BigDecimal bigDecimal);

    /**
     * 返回
     * @return
     */
    Car build();
}

CarBuilder.class

public class CarBuilder implements Builder{
    private final Car car = new Car();

    @Override
    public Builder buildColor(String color) {
        car.setColor(color);
        return this;
    }

    @Override
    public Builder buildType(String type) {
        car.setType(type);
        return this;
    }

    @Override
    public Builder buildName(String name) {
        car.setName(name);
        return this;
    }

    @Override
    public Builder buildPrice(BigDecimal bigDecimal) {
        car.setPrice(bigDecimal);
        return this;
    }

    @Override
    public Car build() {
        return car;
    }
}

这里的处理方式只是做解释,其实还是可以进一步抽象CarBuilder到具体车型的Builder,并在次基础上添加一些验证的功能

CarDirector.class

public class CarDirector {

    public void mpvCarBuilder(Builder builder){
        builder.buildName("奥迪");
        builder.buildType("mpv");
        builder.buildColor("red");
        builder.buildPrice(new BigDecimal("400000.00"));
    }

    public void suvCarBuilder(Builder builder){
        builder.buildName("奥迪");
        builder.buildType("suv");
        builder.buildColor("black");
        builder.buildPrice(new BigDecimal("300000.00"));
    }
}

Client.class

public class Client {
    @Test
    public void builderMvp(){
        CarDirector carDirector = new CarDirector();
        Builder builder = new CarBuilder();
        carDirector.mpvCarBuilder(builder);
        System.out.println(builder.build().toString());
    }

    @Test
    public void buildSuv(){
        CarDirector carDirector = new CarDirector();
        Builder builder = new CarBuilder();
        carDirector.suvCarBuilder(builder);
        System.out.println(builder.build().toString());
    }
}

总结

在日常开发中我们能经常用到Builder设计模式,最常见的就是核心程序中的StringBuilder了,在开源框架中我们也经常能够看到,例如Mybatis中的SqlSourceBuilderXMLConfigBuilder等等信息

为了灵活构造复杂对象,该对象会有多个成员变量,在外部调用的时候,不需要或者不方便一次性创建出所有的成员变量,在这种情况下,使用多个构造方法去构建对象,很难维护,这时候Builder设计模式解决这个问题,进行buid()方法中创建对象,并且将builder传入,该builder中,维护了传入对象的成员变量。