👉文章示例代码👈

定义

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

用户只需指定需要建造的类型就可以得到它们,建造过程及细节不需要知道。

建造者模式注重于方法的调用顺序,而工厂模式注重于创建产品。

四要素

标准建造者模式有四个要素:

  • 产品类:既可以是具体的实体类,也可以是抽象类与其具体实现组成。
  • 抽象建造者:接口或者抽象类,将具体的实现过程移交给子类。
  • 具体建造者:抽象建造者的具体实现类,用于构建产品。
  • 指挥者类:调用合适的建造者方法来构建产品。

场景示例

笔者这里以攒电脑为例。攒机需要购买一些配置,例如:CPU、主板、内存条、硬盘、显卡、机箱、电源、显示器等。然后按照自己的需求和喜好将这些配置攒起来组装成电脑,满足自己的个性化需求。当然也会有一些攒机的商家,来帮用户处理攒机的过程。

创建产品类

/**
 * @author zhh
 * @description 电脑类
 * @date 2020-02-11 14:01
 */
public class Computer {

    /**
     * cpu
     */
    private String cpu;

    /**
     * 主板
     */
    private String mainboard;

    /**
     * 内存
     */
    private String memory;

    /**
     * 硬盘
     */
    private String hardDisk;

    /**
     * 显卡
     */
    private String gpu;

    /**
     * 机箱
     */
    private String crate;

    /**
     * 电源
     */
    private String powerSupply;

    /**
     * 显示器
     */
    private String monitor;

    // 此处省略getter、setter方法

    @Override
    public String toString() {
        return "Computer{" + "cpu='" + cpu + '\'' + ", mainboard='" + mainboard + '\'' + ", memory='" + memory + '\'' +
                ", hardDisk='" + hardDisk + '\'' + ", gpu='" + gpu + '\'' + ", crate='" + crate + '\'' +
                ", powerSupply='" + powerSupply + '\'' + ", monitor='" + monitor + '\'' + '}';
    }
}

创建抽象建造者

抽象电脑建造者类中,额外提供一个组装电脑的方法,其返回参数为产品类。

/**
 * @author zhh
 * @description 抽象电脑建造者类
 * @date 2020-02-11 14:32
 */
public abstract class ComputerBuilder {

    public abstract void buyCpu(String cpu);
    public abstract void buyMainboard(String mainboard);
    public abstract void buyMemory(String memory);
    public abstract void buyHardDisk(String hardDisk);
    public abstract void buyGpu(String gpu);
    public abstract void buyCrate(String crate);
    public abstract void buyPowerSupply(String powerSupply);
    public abstract void buyMonitor(String monitor);

    /**
     * 组装电脑
     */
    public abstract Computer assembleComputer();
}

创建具体建造者

创建具体的建造者类,继承我们的抽象创建者,实现抽象方法。

/**
 * @author zhh
 * @description 实际的电脑建造者类
 * @date 2020-02-11 14:41
 */
public class ComputerActualBuilder extends ComputerBuilder {

    private Computer computer = new Computer();

    @Override
    public void buyCpu(String cpu) {
        computer.setCpu(cpu);
    }

    @Override
    public void buyMainboard(String mainboard) {
        computer.setMainboard(mainboard);
    }

    @Override
    public void buyMemory(String memory) {
        computer.setMemory(memory);
    }

    @Override
    public void buyHardDisk(String hardDisk) {
        computer.setHardDisk(hardDisk);
    }

    @Override
    public void buyGpu(String gpu) {
        computer.setGpu(gpu);
    }

    @Override
    public void buyCrate(String crate) {
        computer.setCrate(crate);
    }

    @Override
    public void buyPowerSupply(String powerSupply) {
        computer.setPowerSupply(powerSupply);
    }

    @Override
    public void buyMonitor(String monitor) {
        computer.setMonitor(monitor);
    }

    @Override
    public Computer assembleComputer() {
        return computer;
    }
}

创建指挥者类

攒机商家是我们的指挥者,商家推荐配置供用户购买参考,帮助用户进行组装。

/**
 * @author zhh
 * @description 商家类
 * @date 2020-02-11 14:55
 */
public class Enterprise {

    private ComputerBuilder computerBuilder;

    public void setComputerBuilder(ComputerBuilder computerBuilder) {
        this.computerBuilder = computerBuilder;
    }

    /**
     * 组装电脑
     */
    public Computer assembleComputer(String cpu, String mainboard,
                                     String memory, String hardDisk,
                                     String gpu, String crate,
                                     String powerSupply, String monitor) {
        computerBuilder.buyCpu(cpu);
        computerBuilder.buyMainboard(mainboard);
        computerBuilder.buyMemory(memory);
        computerBuilder.buyHardDisk(hardDisk);
        computerBuilder.buyGpu(gpu);
        computerBuilder.buyCrate(crate);
        computerBuilder.buyPowerSupply(powerSupply);
        computerBuilder.buyMonitor(monitor);

        return computerBuilder.assembleComputer();
    }
}

测试类及输出

/**
 * @author zhh
 * @description 测试类
 * @date 2020-02-11 15:05
 */
public class Test {
    public static void main(String[] args) {
        ComputerBuilder computerBuilder = new ComputerActualBuilder();
        Enterprise enterprise = new Enterprise();
        enterprise.setComputerBuilder(computerBuilder);
        Computer computer = enterprise.assembleComputer("Intel 酷睿i7 8700K",
                "影驰B360M-M.2",
                "影驰GAMER 8GB DDR4 2400",
                "希捷Barracuda 1TB 7200转 64MB",
                "七彩虹iGame750Ti 烈焰战神U-Twin-2GD5",
                "金河田峥嵘Z30",
                "航嘉WD600K",
                "三星C27F390FHC");

        System.out.println(computer);
    }
}

测试类的输出结果如下:

Computer{cpu=’Intel 酷睿i7 8700K’, mainboard=’影驰B360M-M.2′, memory=’影驰GAMER 8GB DDR4 2400′, hardDisk=’希捷Barracuda 1TB 7200转 64MB’, gpu=’七彩虹iGame750Ti 烈焰战神U-Twin-2GD5′, crate=’金河田峥嵘Z30′, powerSupply=’航嘉WD600K’, monitor=’三星C27F390FHC’}

类结构图

以上示例类的结构图如下所示

image.png

我们可以看到我们的 Test 类和抽象建造者 ComputerBuilder 和产品类 Computer 都没有关系,只和指挥者类 Enterprise 、具体的建造者 ComputerActualBuilder 有关。

Test 类创建指挥者类 Enterprise,指挥者类 Enterprise 通过组合的方式使用 ComputerBuilder ,实际使用 ComputerActualBuilder 创建产品类 Computer 。

示例演进

上述示例建造者的使用方式只是一种标准的使用方式。

我们发现我们的指挥者类并不是必须的。我们可以不需要攒机商家帮忙组装,我们可以自己动手。

下面来进行代码的演进。

调整产品类

这里使用静态内部类,依靠链式调用的方式来调整产品类。

/**
 * @author zhh
 * @description 电脑类
 * @date 2020-02-11 14:01
 */
public class Computer {

    /**
     * cpu
     */
    private String cpu;

    /**
     * 主板
     */
    private String mainboard;

    /**
     * 内存
     */
    private String memory;

    /**
     * 硬盘
     */
    private String hardDisk;

    /**
     * 显卡
     */
    private String gpu;

    /**
     * 机箱
     */
    private String crate;

    /**
     * 电源
     */
    private String powerSupply;

    /**
     * 显示器
     */
    private String monitor;

    public Computer(ComputerBuilder computerBuilder) {
        this.cpu = computerBuilder.cpu;
        this.mainboard = computerBuilder.mainboard;
        this.memory = computerBuilder.memory;
        this.hardDisk = computerBuilder.hardDisk;
        this.gpu = computerBuilder.gpu;
        this.crate = computerBuilder.crate;
        this.powerSupply = computerBuilder.powerSupply;
        this.monitor = computerBuilder.monitor;
    }

    @Override
    public String toString() {
        return "Computer{" + "cpu='" + cpu + '\'' + ", mainboard='" + mainboard + '\'' + ", memory='" + memory + '\'' +
                ", hardDisk='" + hardDisk + '\'' + ", gpu='" + gpu + '\'' + ", crate='" + crate + '\'' +
                ", powerSupply='" + powerSupply + '\'' + ", monitor='" + monitor + '\'' + '}';
    }

    /**
     * 声明静态内部类
     */
    public static class ComputerBuilder {
        /**
         * cpu
         */
        private String cpu;

        /**
         * 主板
         */
        private String mainboard;

        /**
         * 内存
         */
        private String memory;

        /**
         * 硬盘
         */
        private String hardDisk;

        /**
         * 显卡
         */
        private String gpu;

        /**
         * 机箱
         */
        private String crate;

        /**
         * 电源
         */
        private String powerSupply;

        /**
         * 显示器
         */
        private String monitor;

        public ComputerBuilder buyCpu(String cpu){
            this.cpu = cpu;
            return this;
        }

        public ComputerBuilder buyMainboard(String mainboard){
            this.mainboard = mainboard;
            return this;
        }

        public ComputerBuilder buyMemory(String memory){
            this.memory = memory;
            return this;
        }

        public ComputerBuilder buyHardDisk(String hardDisk){
            this.hardDisk = hardDisk;
            return this;
        }

        public ComputerBuilder buyGpu(String gpu){
            this.gpu = gpu;
            return this;
        }

        public ComputerBuilder buyCrate(String crate){
            this.crate = crate;
            return this;
        }

        public ComputerBuilder buyPowerSupply(String powerSupply){
            this.powerSupply = powerSupply;
            return this;
        }

        public ComputerBuilder buyMonitor(String monitor){
            this.monitor = monitor;
            return this;
        }

        public Computer build() {
            return new Computer(this);
        }
    }
}

测试类及输出

/**
 * @author zhh
 * @description 测试类
 * @date 2020-02-11 15:05
 */
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer.ComputerBuilder()
                .buyCpu("Intel 酷睿i7 8700K")
                .buyMainboard("影驰B360M-M.2")
                .buyMemory("影驰GAMER 8GB DDR4 2400")
                .buyHardDisk("希捷Barracuda 1TB 7200转 64MB")
                .buyGpu("七彩虹iGame750Ti 烈焰战神U-Twin-2GD5")
                .buyCrate("金河田峥嵘Z30")
                .buyPowerSupply("航嘉WD600K")
                .buyMonitor("三星C27F390FHC")
                .build();

        System.out.println(computer);
    }
}

测试类的输出结果如下:

Computer{cpu=’Intel 酷睿i7 8700K’, mainboard=’影驰B360M-M.2′, memory=’影驰GAMER 8GB DDR4 2400′, hardDisk=’希捷Barracuda 1TB 7200转 64MB’, gpu=’七彩虹iGame750Ti 烈焰战神U-Twin-2GD5′, crate=’金河田峥嵘Z30′, powerSupply=’航嘉WD600K’, monitor=’三星C27F390FHC’}

类结构图

以上演进的结构图如下所示

image.png

源码中的用例

  • java.lang.StringBuilder 和 java.lang.StringBuffer 
  • Spring 中的 BeanDefinitionBuilder 
  • MyBatis 中的 SqlSessionFactoryBuilder 

总结

适用场景

  • 一个对象有非常复杂的内部结构(很多属性)
  • 想把复杂对象的创建和使用分离

优点

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

缺点

  • 会产生多余的Builder对象
  • 产品内部结构发生变化,建造者都需要修改,成本比较大

参考