初学Java常用设计模式之——建造者模式

181 阅读6分钟

声明:转载请附上原文链接

提示:标题序号从4开始,是照应不同设计模式笔记发布的顺序而定的,比如,第上一篇文章 初学Java常用设计模式之——原型模式 序号从3开始。

4. 建造者模式(常用)

4.1 建造者模式简介

  • 建造者模式(Builder Pattern)

    • 使用多个简单的对象一步一步构建成一个复杂的对象将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
    • 允许用户只通过指定复杂对象的类型和内容就可以构建它们,不需要知道内部的具体构建细节
  • 场景举例

    • FC创建套餐:套餐是一个复杂对象,它一般包含主食如汉堡、烤翅等和饮料 如果汁、 可乐等组成部分,不同的套餐有不同的组合,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐
    • 电脑有低配、高配,组装需要CPU、内存、电源、硬盘、主板等
  • 核心组成

    • Builder:抽象建造者,定义多个通用方法和构建方法
    • ConcreteBuilder:具体建造者,可以有多个
    • Director:指挥者,控制整个组合过程,将需求交给建造者,由建造者去创建对象
    • Product:产品角色

    通过图再来理解下:

    在这里插入图片描述

4.2 建造者模式案例

首先来创建产品类Computer (电脑)

/**
 * @Auther: csp1999
 * @Date: 2020/11/08/10:35
 * @Description: 产品类 Computer
 */
public class Computer {
    private String cpu;
    private String memory;
    private String mainboard;
    private String disk;
    private String power;

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String getMainboard() {
        return mainboard;
    }

    public void setMainboard(String mainboard) {
        this.mainboard = mainboard;
    }

    public String getDisk() {
        return disk;
    }

    public void setDisk(String disk) {
        this.disk = disk;
    }

    public String getPower() {
        return power;
    }

    public void setPower(String power) {
        this.power = power;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", mainboard='" + mainboard + '\'' +
                ", disk='" + disk + '\'' +
                ", power='" + power + '\'' +
                '}';
    }
}

接下来创建抽象建造者接口Builder

/**
 * @Auther: csp1999
 * @Date: 2020/11/08/10:38
 * @Description: 抽象建造者接口
 *
 * 声明建造者的公共方法
 */
public interface Builder {

    /**
     * 接口方法
     */
    void buildCpu();

    void buildMainBoard();

    void buildDisk();

    void buildPower();

    void buildMemory();

    Computer createComputer();
}

然后是创建具体建造者类A (高配电脑建造者)HighComputerBuilder 和 具体建造者类B(低配电脑建造者) LowComputerBuilder

/**
 * @Auther: csp1999
 * @Date: 2020/11/08/10:46
 * @Description: 具体建造者类 A :高配电脑建造者
 */
public class HighComputerBuilder implements Builder {

    private Computer computer = new Computer();

    @Override
    public void buildCpu() {
        computer.setCpu("高配 CPU");
    }

    @Override
    public void buildMainBoard() {
        computer.setMainboard("高配 主板");
    }

    @Override
    public void buildDisk() {
        computer.setDisk("高配 磁盘");
    }

    @Override
    public void buildPower() {
        computer.setPower("高配 电源");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("高配 内存");
    }

    @Override
    public Computer createComputer() {
        return computer;// 返回computer对象
    }
}
/**
 * @Auther: csp1999
 * @Date: 2020/11/08/10:46
 * @Description: 具体建造者类 B :低配电脑建造者
 */
public class LowComputerBuilder implements Builder {

    private Computer computer = new Computer();

    @Override
    public void buildCpu() {
        computer.setCpu("低配 CPU");
    }

    @Override
    public void buildMainBoard() {
        computer.setMainboard("低配 主板");
    }

    @Override
    public void buildDisk() {
        computer.setDisk("低配 磁盘");
    }

    @Override
    public void buildPower() {
        computer.setPower("低配 电源");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("低配 内存");
    }

    @Override
    public Computer createComputer() {
        return computer;// 返回computer对象
    }
}

最后是指挥者类**Director ** 控制产品生产过程:

/**
 * @Auther: csp1999
 * @Date: 2020/11/08/10:50
 * @Description: 指挥者类:控制整个组合过程,将需求交给建造者,由建造者去创建对象
 *
 * 将产品和创建过程进行解耦,使用相同的创建过程创建不同的产品,控制产品生产过程
 *
 * Director 是全程指导组装过程,具体细节还是由builder 去操作
 */
public class Director {

    public Computer create(Builder builder){
        builder.buildCpu();
        builder.buildDisk();
        builder.buildMainBoard();
        builder.buildMemory();
        builder.buildPower();

        return builder.createComputer();
    }
}

完成后我们来进行测试:

@Test
public void testBuilder(){
    Director director = new Director();// 声明指挥者
    // 指挥者指挥构建低配电脑
    Computer low_computer = director.create(new LowComputerBuilder());
    // 指挥者指挥构建高配电脑
    Computer high_computer = director.create(new HighComputerBuilder());
    System.out.println(low_computer);
    System.out.println(high_computer);
}

输出结果:

Computer{cpu='低配 CPU', memory='低配 内存', mainboard='低配 主板', disk='低配 磁盘', power='低配 电源'}
Computer{cpu='高配 CPU', memory='高配 内存', mainboard='高配 主板', disk='高配 磁盘', power='高配 电源'}

建造者模式案例完成!

4.3 小结

  • 建造者模式优点

    • 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦
    • 每一个具体建造者都相对独立,而与其他的具体建造者无关,更加精细地控制产品的创建过程
    • 增加新的具体建造者无须修改原有类库的代码,符合开闭原则
    • 建造者模式结合链式编程来使用,代码上更加美观
  • 建造者模式缺点

    • 建造者模式所创建的产品一般具有较多的共同点,如果产品差异大则不建议使用
  • JDK里面的应用

    • tcp传输协议 protobuf 生成的api、java中的StringBuilder(不完全一样,思想一样)
  • 建造者模式与抽象工厂模式的比较:

    • 建造者模式返回一个组装好的完整产品 , 抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族
    • 建造者模式是把对象的创建分散开来,每个抽象方法负责其中的一部分抽象工厂是每个方法负责一个产品族
    • 建造者模式所有函数加到一起才能生成一个对象。抽象工厂一个函数生成一个对象

到这里可能大家还是有些不太理解抽象工厂模式建造者模式的区别,这里再简单举一个例子:

  • 比如华为手机制造,华为荣耀系列 和 华为Nova系列的产品生产交给手机生产承包商(FactoryProducer 超级⼯⼚创造器) ,承包商旗下有专门负责生产华为手机职能(接口/抽象类中的方法)的工厂(IFactory抽象⼯⼚),这个抽象工厂有两个子厂分别负责实际生产荣耀系列手机(荣耀产品族) 和 华为Nova系列手机(Nova产品族),从这两个子工厂中生产出来产品,荣耀手机(荣耀产品族的产品) 和 华为Nova手机(Nova产品族的产品),这一流程属于抽象工厂模式
  • 还是上面的例子,从两个子工厂的生产流水线上拼凑组装华为手机产品的过程叫做建造者模式,以负责Nova手机生产的子厂为例,当前生产线的负责人(Director 指挥者)指导流水线生产Nova系列手机的Nova 4 型号(director.create(new Nova4());) 其中具体建造组装该型号手机的流程被封装在new Nova4()中,如果指挥者临时需要流水线去组装Nova 5型号的手机产品,那么只需要director.create(new Nova5());即可。

为了方便大家对比工厂模式和建造者模式的区别,这里放上初学Java常用设计模式之——工厂模式 学习链接!

之后我会陆续更新其他设计模式博文,如果文章对您有帮助,希望点个赞/收藏/关注! O(∩_∩)O~