当前位置: 首页 > news >正文

设计模式 —— 建造者模式

简介

在软件开发中,存在大量复杂对象,它们拥有一系列成员属性,这些成员属性中有些是引用类型的成员对象。而且在这些复杂对象中,还可能存在一些限制条件,如某些属性没有赋值则复杂对象不能作为一个完整的产品使用;有些属性的赋值必须按照某个顺序,一个属性没有赋值之前,另一个属性可能无法赋值等。

由于组合部件的过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象里,建造者返还给客户端的是一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式,这就是建造者模式的模式动机。

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

实例

建造者模式包含如下角色:

  1. Builder:抽象建造者
  2. ConcreteBuilder:具体建造者
  3. Director:指挥者
  4. Product:产品

电脑是每个程序员的标配,主要配件有:CPU、主板、内存、显卡、电源。当前主要有两大平台:AMDIntel,但是两个平台的一些零件是不一样的。所以肥宅在组装两个平台时选择的配件也是不一样的。

产品(电脑):

public class Computer {
    /**
     * cpu
     */
    private String cpu;
    /**
     * 主板
     */
    private String motherboar;
    /**
     * 内存
     */
    private String ram;
    /**
     * 显卡
     */
    private String graphicsCard;
    /**
     * 电源
     */
    private String power;

    //setter and getter
    // toString
}
复制代码

抽象工厂:

abstract class AbstractComputerBuilder {
    /**
     * 选择CPU
     */
    abstract void buildCPU();
    /**
     * 选择主板
     */
    abstract void buildMotherboar();
    /**
     * 选择内存
     */
    abstract void buildRam();
    /**
     * 选择显卡
     */
    abstract void buildGraphicsCard();
    /**
     * 选择电源
     */
    abstract void buildPower();
    /**
     * 获取电脑
     */
    abstract Computer getComputer();
}
复制代码

具体建造者:

// AMD电脑 建造者
public class AmdComputerBuilder extends AbstractComputerBuilder {
    private Computer computer = new Computer();
    @Override
    void buildCPU() {
        computer.setCpu("2700x");
    }
    @Override
    void buildMotherboar() {
        computer.setMotherboar("华硕 ROG X470");
    }
    @Override
    void buildRam() {
        computer.setRam("芝奇 DDR4 8G");
    }
    @Override
    void buildGraphicsCard() {
        computer.setGraphicsCard("vega 56");
    }
    @Override
    void buildPower() {
        computer.setPower("EVGA 750W");
    }
    @Override
    Computer getComputer() {
        return computer;
    }
}

// Intel 电脑建造者
public class IntelComputerBuilder extends AbstractComputerBuilder {
    private Computer computer = new Computer();
    @Override
    void buildCPU() {
        computer.setCpu("i7 8700");
    }
    @Override
    void buildMotherboar() {
        computer.setMotherboar("微星 Z370");
    }
    @Override
    void buildRam() {
        computer.setRam("金士顿 DDR4 8G");
    }
    @Override
    void buildGraphicsCard() {
        computer.setGraphicsCard("GTX 1080Ti");
    }
    @Override
    void buildPower() {
        computer.setPower("海韵 750W");
    }
    @Override
    Computer getComputer() {
        return computer;
    }
}
复制代码

指挥者:

public class ComputerDirector {
    public void construct(AbstractComputerBuilder builder) {
        builder.buildCPU();
        builder.buildMotherboar();
        builder.buildRam();
        builder.buildGraphicsCard();
        builder.buildPower();
    }
}
复制代码

测试:

public class Fz {
    @Test
    public void build() {
        ComputerDirector director = new ComputerDirector();

        AmdComputerBuilder amdComputerBuilder = new AmdComputerBuilder();
        director.construct(amdComputerBuilder);
        Computer amdComputer = amdComputerBuilder.getComputer();
        System.out.println("选择AMD平台配件:" + amdComputer);

        IntelComputerBuilder intelComputerBuilder = new IntelComputerBuilder();
        director.construct(intelComputerBuilder);
        Computer intelComputer = intelComputerBuilder.getComputer();
        System.out.println("选择Intel平台配件:" + intelComputer);

    }

}
复制代码

类图

优点

  1. 建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
  2. 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  3. 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
  4. 建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。符合开闭原则。

缺点

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

适用场景

在以下情况下可以使用建造者模式:

  1. 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
  2. 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
  3. 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
  4. 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

总结

建造者模式与工厂模式类似,适用的场景也很相似。建造者模式仅仅只比工厂模式多了一个”指挥者”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。

建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。建造者模式更加关注与零件装配的顺序。

一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。

转载于:https://juejin.im/post/5c7d47f9e51d453eea5dedd2

相关文章:

  • OpenAI发布大型强化深度学习模拟器Neural MMO,AI适者生存择最优
  • 新手站长们看过来:白话ID
  • 华山模拟器安装
  • SQL查询数据时报错
  • yarn的常用命令
  • 三步搞定js类型转换
  • 深入数组切片
  • Spring入门(一):创建Spring项目
  • 如何判断我们的代理ip是高匿
  • Java初学者最佳的学习方法以及会遇到的坑(内含学习资料)!
  • python发送邮件
  • VMware下ubuntu与Windows实现文件共享的方法(zhuan)
  • 接口测试与Postman
  • antiX 17.4 发布,轻量级 Linux 发行版
  • ansible一键部署脚本
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • JavaScript设计模式之工厂模式
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Netty 4.1 源代码学习:线程模型
  • Rancher-k8s加速安装文档
  • React系列之 Redux 架构模式
  • Sequelize 中文文档 v4 - Getting started - 入门
  • Sublime Text 2/3 绑定Eclipse快捷键
  • v-if和v-for连用出现的问题
  • XForms - 更强大的Form
  • 闭包,sync使用细节
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 技术:超级实用的电脑小技巧
  • 理清楚Vue的结构
  • 力扣(LeetCode)21
  • 前端面试之CSS3新特性
  • 首页查询功能的一次实现过程
  • 源码安装memcached和php memcache扩展
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • Android开发者必备:推荐一款助力开发的开源APP
  • ionic入门之数据绑定显示-1
  • zabbix3.2监控linux磁盘IO
  • 通过调用文摘列表API获取文摘
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #在 README.md 中生成项目目录结构
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (三)elasticsearch 源码之启动流程分析
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (转)大型网站架构演变和知识体系
  • (转)关于多人操作数据的处理策略
  • ../depcomp: line 571: exec: g++: not found
  • .net core 6 集成和使用 mongodb
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .net 调用php,php 调用.net com组件 --
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .NET基础篇——反射的奥妙
  • @EventListener注解使用说明
  • @NestedConfigurationProperty 注解用法