设计模式-建造者模式

2023-11-19

建造者模式:创建复杂对象的优雅方式

在软件开发中,有时候我们需要创建具有复杂结构和多个组件的对象。直接在客户端代码中实例化这种对象并设置其属性可能会变得非常冗长和难以维护。这就是建造者模式的用武之地。建造者模式提供了一种优雅的方式来构建复杂对象,同时保持代码的可读性和可维护性。在本文中,我们将深入探讨建造者模式的概念,并通过Java代码示例来说明其用法。

什么是建造者模式?

建造者模式(Builder Pattern)是一种创建型设计模式,旨在解决创建复杂对象的问题。它将一个对象的构建过程封装在一个独立的建造者类中,客户端代码使用建造者来一步一步构建对象。这使得客户端代码不需要了解对象的内部构建细节,同时允许在创建过程中灵活地添加、修改或替换组件。

建造者模式通常包括以下关键组件:

  1. 产品类(Product): 表示待构建的复杂对象,包含多个组件。

  2. 抽象建造者类(Builder): 声明了构建产品的抽象方法,通常包括设置各个组件的方法。

  3. 具体建造者类(Concrete Builder): 实现了抽象建造者接口,负责构建具体产品的各个组件,同时提供方法链以支持流畅的构建。

  4. 指挥者类(Director): 负责使用建造者来构建产品,它不直接创建产品,而是调用建造者的方法来构建。

建造者模式的使用场景

建造者模式适用于以下情况:

  1. 需要创建复杂对象: 当对象具有多个组件或配置项,并且其构建过程复杂且多变时,建造者模式可以提供一种清晰的方式来构建对象。

  2. 需要避免构造器参数列表过长: 如果一个类有很多属性,将它们全部作为构造器参数传递可能会导致构造器参数列表非常冗长,难以维护。建造者模式可以将构造参数拆分成多个方法,使代码更加清晰。

  3. 需要创建不可变对象: 建造者模式通常与不可变对象一起使用,因为对象的构建是在构造过程中完成的,一旦构建完成,对象的状态不再改变。

  4. 需要重用构建逻辑: 如果您需要在不同的场景中构建相似但稍有不同的对象,建造者模式可以帮助您重用构建逻辑。

优缺点

建造者模式(Builder Pattern)是一种创建型设计模式,用于创建复杂对象,将对象的构建过程与其表示分离。这种模式通过将对象的构建过程分解为一系列步骤,并允许客户端按照自己的需求逐步构建对象,从而使得构建过程更加灵活,同时也降低了构建过程的复杂性。下面是建造者模式的优缺点:

优点:

  1. 分离构建过程和表示:建造者模式允许客户端逐步构建对象,而不必知道对象的内部细节。这样可以隐藏对象的复杂性,使客户端只需要关注构建过程,而不必关心对象的组成部分。

  2. 可配置性:建造者模式允许客户端根据需要配置对象的不同属性,从而创建不同的对象实例。这使得在不同情况下可以使用相同的构建过程创建不同的对象,提高了代码的可重用性。

  3. 灵活性:由于构建过程是分步进行的,客户端可以灵活地控制每个步骤的执行顺序和参数,从而满足不同的需求,使得对象的构建更加灵活。

  4. 避免重叠构造器模式:相对于使用多个重叠构造器方法来创建对象,建造者模式提供了一种更加清晰和可读的方式来构建对象,避免了构造器方法的混淆和过多的参数。

  5. 可以用于创建不可变对象:通过建造者模式创建的对象可以设计成不可变对象,从而保证对象的一致性和线程安全性。

缺点:

  1. 增加了代码复杂性:引入建造者模式会增加代码的复杂性,因为需要创建一个额外的建造者类,并定义多个步骤的构建方法。这可能会导致代码量增加。

  2. 需要额外的开发工作:建造者模式需要额外的开发工作来创建建造者类和定义构建步骤。对于简单的对象,这可能会显得过于繁琐。

  3. 不适用于所有情况:建造者模式主要适用于创建复杂对象的情况,对于简单对象或者对象的构建过程非常简单的情况,使用建造者模式可能会显得过于繁重。

总的来说,建造者模式在需要创建复杂对象并希望将构建过程与表示分离的情况下是一个有用的设计模式。然而,它也有一些开发和维护成本,因此需要在具体情况下仔细考虑是否使用。

示例:使用建造者模式创建电脑对象

让我们通过一个简单的示例来演示建造者模式的用法。我们将创建一个电脑对象,该电脑具有多个组件,例如 CPU、内存、硬盘、显卡等。我们将使用建造者模式来构建电脑对象。

首先,定义产品类 Computer

public class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;
    private String graphicsCard;

    public Computer(String cpu, String memory, String hardDisk, String graphicsCard) {
        this.cpu = cpu;
        this.memory = memory;
        this.hardDisk = hardDisk;
        this.graphicsCard = graphicsCard;
    }

    // Getter methods
    // ...
}

接下来,定义抽象建造者接口 ComputerBuilder

public interface ComputerBuilder {
    ComputerBuilder setCPU(String cpu);
    ComputerBuilder setMemory(String memory);
    ComputerBuilder setHardDisk(String hardDisk);
    ComputerBuilder setGraphicsCard(String graphicsCard);
    Computer build();
}

然后,实现具体建造者类 DesktopBuilderLaptopBuilder

public class DesktopBuilder implements ComputerBuilder {
    private String cpu;
    private String memory;
    private String hardDisk;
    private String graphicsCard;

    @Override
    public ComputerBuilder setCPU(String cpu) {
        this.cpu = cpu;
        return this;
    }

    @Override
    public ComputerBuilder setMemory(String memory) {
        this.memory = memory;
        return this;
    }

    @Override
    public ComputerBuilder setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
        return this;
    }

    @Override
    public ComputerBuilder setGraphicsCard(String graphicsCard) {
        this.graphicsCard = graphicsCard;
        return this;
    }

    @Override
    public Computer build() {
        return new Computer(cpu, memory, hardDisk, graphicsCard);
    }
}

public class LaptopBuilder implements ComputerBuilder {
    private String cpu;
    private String memory;
    private String hardDisk;
    private String graphicsCard;

    @Override
    public ComputerBuilder setCPU(String cpu) {
        this.cpu = cpu;
        return this;
    }

    @Override
    public ComputerBuilder setMemory(String memory) {
        this.memory = memory;
        return this;
    }

    @Override
    public ComputerBuilder setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
        return this;
    }

    @Override
    public ComputerBuilder setGraphicsCard(String graphicsCard) {
        this.graphicsCard = graphicsCard;
        return this;
    }

    @Override
    public Computer build() {
        return new Computer(cpu, memory, hardDisk, graphicsCard);
    }
}

最后,创建指挥者类 ComputerDirector 用于构建电脑对象:

public class ComputerDirector {
    public Computer buildComputer(ComputerBuilder builder) {
        return builder.build();
    }
}

现在,我们可以在客户端代码中使用建造者模式来构建不同类型的电脑对象:

public class Client {
    public static void main(String[] args) {
        ComputerDirector director = new ComputerDirector();

        Computer desktop = director.buildComputer(new Desktop
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式-建造者模式 的相关文章

  • 方法返回类型前的 是什么意思?

    下面的方法返回一个List组成T类型元素 public
  • 在Maven中生成Version.java文件

    我有一个使用 Ant 脚本构建的 Java 项目 我正在尝试将项目转换为 Maven 其中一项任务生成一个名为 Version java 的 Java 源文件 其中包含编译时间戳的静态字符串表示形式 如下所示 package com foo
  • 连接外部 Accumulo 实例和 java

    我正在尝试使用 Accumulo 连接到虚拟机 问题是 我无法将其连接到 Java 中 我可以看到 Apache 抛出的网页 但我无法让它与代码一起工作 我认为这是缺乏知识的问题而不是真正的问题 但我找不到这方面的文档 所有示例都使用 lo
  • 在不支持 CAS 操作的处理器上进行 CompareAndSet

    今天 我在一次采访中被问到下一个问题 如果您在具有不支持 CAS 操作的处理器的机器上调用 AtomicLong 的compareAndSet 方法 会发生什么情况 您能否帮我解决这个问题 并在可能的情况下提供一些全面描述的链接 From
  • 如何以编程方式使用包含多列的 where-in 子句执行 PostgreSQL 查询?

    我的查询是这样的 select from plat customs complex where code t code s in 01013090 10 01029010 90 它在 psql 控制台中运行良好 我的问题是如何在客户端代码中
  • 查看Java Agent修改的Java类的源代码

    我需要了解 Java 代理如何修改我的初始类 以便我能够理解代码的作用 build gradle configurations jar archiveName agent2 jar jar manifest attributes Prema
  • 使用 OkHttp 下载损坏的文件

    我编写的下载文件的方法总是会产生损坏的文件 public static String okDownloadToFileSync final String link final String fileName final boolean te
  • 如何使用 Java Apache POI 隐藏 Excel 工作表中以下未使用的行?

    我正在使用数据库中的数据填充模板 Excel 工作表 for Map
  • getCurrentSession 在网络中休眠

    我正在使用 hibernate 和 jsp servlet 编写一个基于 Web 的应用程序 我读过有关sessionFactory getCurrentSession and sessionFactory openSession方法 我知
  • 将类转换为 JSONObject

    我有好几堂这样的课 我想将类转换为 JSONObject 格式 import java io Serializable import com google gson annotations SerializedName public cla
  • ThreeTen 向后移植与 JSR-310 的比较

    由于某些原因 我们现在无法使用 java 8 我们仍然停留在 java 7 上 不过 我想使用新的JSR 310 date time APIs现在 使用官方向后移植 ThreeTen http www threeten org threet
  • 使用 JDBC 连接到 PostgreSql 的本地实例

    我在 Linux 机器上有一个正在运行的 PostgreSql 本地实例 当我使用psql来自 shell 的命令我成功登录 没有任何问题 我需要通过 JDBC 连接到 PostgreSql 但我不知道我到底应该传递什么url参数为Driv
  • 如何在 IntelliJ IDEA 中运行 akka actor

    来自 Akka 网站文档 然后 这个主要方法将创建所需的基础设施 运行演员 启动给定的主要演员并安排 一旦主要参与者终止 整个应用程序就会关闭 因此 您将能够使用类似于以下的命令运行上面的代码 下列的 java classpath akka
  • Android 认为我没有关闭数据库!为什么?

    我有一个 SQLiteDatabase 数据成员 我在 onCreate 中初始化它 并在 onPause onStop 和 onDestroy 中调用 close 它在 onResume 中重新初始化 它似乎运行得很好 但当我查看调试器时
  • 如何自定义舍入形式

    我的问题可能看起来很简单 但仍然无法得到有效的东西 我需要自定义 Math round 舍入格式或其他格式以使其工作如下 如果数字是 1 6 他应该四舍五入到 1 如果大于或等于 1 7 他应该四舍五入到 2 0 对于所有其他带有 6 的小
  • Android - 存储对ApplicationContext的引用

    我有一个静态 Preferences 类 其中包含一些应用程序首选项和类似的内容 可以在那里存储对 ApplicationContext 的引用吗 我需要该引用 以便我可以在不继承 Activity 的类中获取缓存文件夹和类似内容 你使用的
  • Tomcat 6 未从 WEB-INF/lib 加载 jar

    我正在尝试找出我的 tomcat 环境中的配置问题 我们的生产服务器正在运行 tomcat 安装并从共享 NFS 挂载读取战争 然而 当我尝试使用独立的盒子 及其配置 进行同样的战争时 我收到下面发布的错误 有趣的是 如果我将 WEB IN
  • 即使禁用安全性,OAuth 令牌 API 也无法在 Elastic Search 中工作

    我是 Elastic search 新手 使用 Elastic search 版本 7 7 1 我想通过以下方式生成 OAuth 令牌弹性搜索文档 https www elastic co guide en elasticsearch re
  • 用于请求带有临时缓存的远程 Observable 的 RxJava 模式

    用例是这样的 我想暂时缓存最新发出的昂贵的Observable响应 但在它过期后 返回到昂贵的源Observable并再次缓存它 等等 一个非常基本的网络缓存场景 但我真的很难让它工作 private Observable
  • 检测到 JVM 正在关闭

    我有一个使用 addShutdownHook 处理 Ctrl C 的 Swing 应用程序 它工作正常 直到我的关闭任务之一调用一个在正常情况下更改 JLabel 文本的函数 此时它挂起 我认为问题是 Swing EDT 已终止或正在等待某

随机推荐

  • matlab 从点云中移除隐藏点

    目录 一 功能概述 1 算法概述 2 主要函数 二 代码实现 三 结果展示 四 参考链接 一 功能概述 1 算法概述 该函数使用如下步骤从指定的视点确定点云中的可见点 1 将点云与中心位于视点的坐标系相关联 2 使用球形投影进行反演 创建一
  • nginx配置vue(history模式)

    问题的原因 项目本来使用 hash 的路由模式来部署 因为需求关系 现在要改成 history 的模式来部署了 路径上不要有 号 第一步 修改项目的 router index js 的配置 const router new VueRoute
  • modbus总线协议(一)modbus rtu

    一 介绍 Modbus协议由Modicon公司开发出来 现在Modbus是工业领域全球最流行的协议 硬件支持RS 232 RS 422 RS 485和以太网设备 应用在PLC DCS 智能仪表等工控领域 图片来源于网络 二 modbus协议
  • template 的使用

    插件介绍 template 是一个高性能的JavaScript模板引擎 插件特性 1 性能卓越 执行速度快 mustache 与 tmpl 的20多倍 2 支持运行时调试 可精准定位异常模板所在语句 3 对 NodeJS Express 有
  • Java NIO Files类读取文件流方式详解

    Java NIO Files类读取文件流方式详解 Files类原理概述 java nio file Files是Java标准库提供的一个工具类 用于操作文件和目录 它提供了一系列静态方法 可以用于创建 复制 删除 移动 重命名 读取 写入文
  • Kaggle研究16,000+数据科学从业者并公开数据 !(附数据集下载)

    来源 机器之心 本文长度为2540字 建议阅读5分钟 本文整理Kaggle对人工智能领域超过16 000受调查者的调查数据结果 Kaggle 是互联网上最著名的数据科学竞赛平台之一 今年3月8日 这家机构被谷歌收购 6月6日又宣布用户数量超
  • 二进制.bin文件切分、bintopng、write

    import numpy as np import cv2 import os Your file path file dep open r E data 3DHuman Detection withoutlabel 20180715 50
  • 小白入门机器学习深度学习实战教程

    课程介绍 机器学习深度学习 实战训练营开课了 哔哩哔哩 bilibili 机器学习深度学习 实战训练营开课了
  • Leetcode——350. 两个数组的交集 II

    题目 给你两个整数数组 nums1 和 nums2 请你以数组形式返回两数组的交集 返回结果中每个元素出现的次数 应与元素在两个数组中都出现的次数一致 如果出现次数不一致 则考虑取较小值 可以不考虑输出结果的顺序 输入 nums1 1 2
  • 关于gitee的用法

    一 安装git 安装git git version 查看版本 创建仓库 git 全局配置 git config global user name huangkaihk git config global user email 邮箱 git
  • 2.6.1 ADSL技术

    ADSL技术 即 非对称数字用户线技术 利用 数字技术 对 现有的 模拟电话用户线 进行改造 使其能够承载宽带数字业务 标准模拟电话信号的 频带 被限制在 300 3400 Hz 的范围内 无法承载宽带数字业务 但 用户线本身 可通过的 信
  • 超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!

    小Hub领读 前后端分离的博客项目终于出来啦 真是花了好多心思录制咧 文末直接进入B站看视频哈 这次你找不到不关注我B站的理由了吧 作者 吕一明 项目代码 https github com MarkerHub vueblog 项目视频 ht
  • Unity卡死情况

    今天遇到了Unity点击播放后卡死 用任务管理器强行关闭后重开 打不开项目的情况 解决方案 检查USB接口设备 有些设备可能会影响Unity工程启动 比如VR头盔
  • 使用java代码给Excel加水印,代码全,进阶版

    以下代码 亲测可以跑通 1 上一篇博客用了Apache POI库3 8的版本的形式对Excel加了水印 但是最近主线版本用了4 1 2的形式 由于为了保持版本的兼容性 下面有开发了Apache POI的4 1 2的版本号的方案 pom文件为
  • 使用selenium IDE开始简易自动化测试

    使用selenium IDE开始简易自动化测试 火狐浏览器有个很好用的selenium插件 可以自动录制页面动作 selenium IDE 下载地址 下载安装好 笔者下载的2 9 0 我们以在百度搜索selenium为例 首先启动IDE 点
  • 链式二叉树的基本操作(C语言实现)

    目录 一 链式二叉树的创建 1 1 定义节点结构 1 2 节点的创建 1 3 节点的链接 二 树的深度遍历 1 前序 中序 后序遍历 1 2 三种方式的遍历顺序图 2 代码实现 3 遍历检测 三 树的层序遍历 3 1 层序遍历 3 2 完全
  • Loadrunner录制登录,验证是否登录成功的几种方法

    1 利用web reg find 优先使用 2 利用web image check 其次 3 利用web get int property函数 4 利用提交的status状态 5 利用对数据的操作查看是否登录 1 利用添加检查点web re
  • 拼多多招收java开发的三轮面试题,你能撑到第几轮?

    我相信 面试一直是大家关注的问题 包括最近有很多刚毕业或者刚实习的小伙伴跟我讲投了很多简历出去 但却都像泥牛入海一样了无音讯了 确实出于程序员的直觉 今年着实是要比往年要更冷一些 对于面试来说 我相信大家都听过一个说法就是 金九银十 但是现
  • c++/cuda并行累计求和

    文章目录 代码 CMakeLists txt 结果 代码 include
  • 设计模式-建造者模式

    文章目录 建造者模式 创建复杂对象的优雅方式 什么是建造者模式 建造者模式的使用场景 优缺点 示例 使用建造者模式创建电脑对象 建造者模式 创建复杂对象的优雅方式 在软件开发中 有时候我们需要创建具有复杂结构和多个组件的对象 直接在客户端代