JAVA 建造者模式(Builder Pattern)

说明

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

用户只需要 指定 需要建造的类型 就可以 得到该类型对应的产品实例 , 不关心建造过程细节 ;

建造者模式类型 : 创建型 ;

应用场景

  • 对象有 非常复杂的内部结构,有很多属性 ;
  • 把 复杂对象 的 创建 和 使用 分离 ;
  • 当创造一个对象 需要 很多步骤时 , 适合使用建造者模式 ;

真实案例

  • flink的 JdbcConnectionOptions 类构建过程

优点

封装性好 : 创建 和 使用 分离 ;
扩展性好 : 建造类之间 相互独立 , 在 一定程度上解耦 ;

缺点

增加类数量 : 产生多余的 Builder 对象 ;
内部修改困难 : 如果 产品内部发生变化 , 建造者也要相应修改 ;

角色

所谓角色,表示分哪几种类

  • 产品(Product):也就是要建造的对象,一般是较为复杂的对象,由一系列部件组成

  • 抽象建造者(builder):其实就是接口或抽象类,表示建造者必须实现的方法。定义具体建造者的公开方法

  • 具体建造者(ConcreteBuilder):抽象建造者的实现类,产品对象是 复杂对象,构建过程可能涉及 多个步骤 和 配置选项,所以作用:

    • 创建产品对象

    • 调用产品对象的 setXXX() 方法,给产品成员变量赋值

    • 按照顺序调用产品对象的方法,以完成构建

  • 指挥者(Director):调用具体建造者来创建复杂对象(产品),并且是按照一定顺序(流程)。(普通程序员就是调用该类来完成创建对象的)

案例

盖楼,需要设置 名称、层数、面积

调用 修建地基、盖楼、封顶 方法

注意:

  • 创建对象时,必须调用 修建地基、盖楼、封顶 方法
  • 方法有调用顺序

产品类

这是的 House 类,就是产品类

package day3;

public class House {
    /**
     * 楼的名字
     */
    private String name;
    /**
     * 房子的层数
     */
    private int floor;
    /**
     * 面积
     */
    private double area;

    public void diji(){
        System.out.println("修建地基");
    }
    public void gailou(){
        System.out.println("盖楼");
    }
    public void fengding(){
        System.out.println("封顶");
    }

    public String getName() {
        return name;
    }

    public int getFloor() {
        return floor;
    }

    public double getArea() {
        return area;
    }
    public void setName(String name) {
        this.name = name;
    }

    public void setFloor(int floor) {
        this.floor = floor;
    }

    public void setArea(double area) {
        this.area = area;
    }
}

抽象建造者

其实就是接口

// 抽象建造者
interface HouseBuilder {
    void setName(String name);
    void setFloor(int floor);
    void setArea(double area);
    // 修筑地基,方法是动词所以加build
    void buildDiji();
    void gailou(); // 盖楼
    void fengding(); // 封顶
    House getProduct();
}

具体建造者

抽象建造者的实现类

class HouseBuilderImpl implements HouseBuilder{
    // 产品类对象
    private House house = new House();

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

    public void setFloor(int floor) {
        house.floor = floor;
    }

    public void setArea(double area) {
        house.area = area;
    }

    // 修筑地基,方法是动词所以加build
    public void buildDiji(){
        house.diji();
    }
    void gailou(){ // 盖楼
        house.gailou();
    }
    void fengding(){ // 封顶
        house.fengding();
    }
    public House getProduct(){
        return house;
    }

}

指挥官

// 指挥者
class Director {
    private HouseBuilder builder;//接口类型

    public Director(HouseBuilder builder) {
        this.builder = builder;
    }

    public House build(String name,int floor,double area) {
        // 设置产品的成员变量
        builder.setName(name);
        builder.setFloor(floor);
        builder.setArea(area);
        //指挥建造者来一步步创建,注意:这些方法有调用顺序,先地基,然后盖楼,最后封顶
        // 先建地基
        builder.diji();
        // 然后盖楼
        builder.gailou();
        // 最后封顶
        builder.fengding();
        return house.getProduct();
    }
}

客户端使用

// 客户端代码,普通程序员编写的代码
public class BuilderExample {
    public static void main(String[] args) {
        // 创建建造者对象
        HouseBuilder builder = new HouseBuilderImpl();
        //创建指挥官对象,builder建造者对象传入指挥者对象
        Director director = new Director(builder);
        // 创建对象
        House house = director.build();

        System.out.println(house);
    }
}

简化建造者

package day3;

public class House {
    /**
     * 楼的名字
     */
    private String name;
    /**
     * 房子的层数
     */
    private int floor;
    /**
     * 面积
     */
    private double area;

    protected House(String name, int floor, double area) {
        this.name = name;
        this.floor = floor;
        this.area = area;
    }

    public void diji(){
        System.out.println("修建地基");
    }
    public void gailou(){
        System.out.println("盖楼");
    }
    public void fengding(){
        System.out.println("封顶");
    }

    public String getName() {
        return name;
    }

    public int getFloor() {
        return floor;
    }

    public double getArea() {
        return area;
    }

    // 定义内部建造者类,通过该类创建产品对象
    static class Builder{
        /**
         * 楼的名字
         */
        private String name;
        /**
         * 房子的层数
         */
        private int floor;
        /**
         * 面积
         */
        private double area;

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

        public Builder setFloor(int floor) {
            this.floor = floor;
            return this;
        }

        public Builder setArea(double area) {
            this.area = area;
            return this;
        }

        /**
         * 在该方法中构建对象
         * @return
         */
        public House build(){
            House house = new House(name, floor, area);
            // 先建地基
            house.diji();
            // 然后盖楼
            house.gailou();
            // 最后封顶
            house.fengding();
            return house;
        }
    }
}

参考:
https://developer.aliyun.com/article/864600
https://www.jianshu.com/p/47329a94f5dc


原文出处:/show_1IX4Xri5bu9M.html