创建型设计模式 - 建造者设计模式 - JAVA

建造者设计模式

    • 一. 简介
    • 二. 使用场景分析
    • 三. 代码案例
      • 3.1 创建ComputerBuilder 类
      • 3.2 修改子类
      • 3.3 修改工厂
      • 3.4 测试
    • 四. 建造者模式案例

前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。
作者:神的孩子都在歌唱

一. 简介

以下是百度百科 对建造者模式的解释 : 文章地址

建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  1. 解决问题

    • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。

    • 当构造过程必须允许被构造的对象有不同表示时。

  2. 在这样的设计模式中,有以下几个角色:

    • builder:为创建一个产品对象的各个部件指定抽象接口。

    • ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。

    • Director:构造一个使用Builder接口的对象。

    • Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口

img

个人理解:建造者模式就是将一大堆东西抽象出来,然后将这些东西拼接成一个不一样的东西(把这当成组装更好理解)

二. 使用场景分析

温馨提示:以下场景分析是我看了几篇建造者模式的文章,然后以自己的理解去编写代码案例总结下来的结论,如果有理解不对的地方或者可以补充的地方请指出

以下是我工厂模式文章举的例子:

image-20231224211149766

这个工厂 可以通过指定磁盘内存 两个参数 去创建一台电脑computer的对象,可是我想在加上一个是否使用喇叭 isSpeaker 的参数 ,有些电脑需要喇叭,有些不需要,所以这个参数不是必须填的了,可是在之前的工厂中,你想创建一台电脑,你就必须要输入指定的参数才可以,可能有很多人说不需要speaker 就输入null就可以了,可是如果这种类似的参数很多呢,要一个个输入null吗?显然是不行的。并且memory和disk是必须输入的参数,这种参数能否和isSpeaker这种可选的参数区分开,方便管理呢?这时候就需要建造者模式去解决这种问题了。

总结上面我个人思考的观点:建造者模式的引入是为了解决工厂和抽象工厂设计模式在对象包含大量属性时的一些问题。当对象包含大量属性时,工厂和抽象工厂设计模式存在三个主要问题。

  1. 从客户端程序传递到 Factory 类的参数太多,这很容易出错,因为大多数时候,参数的类型是相同的,并且从客户端很难维护参数的顺序。
  2. 有些参数可能是可选的,但在工厂模式中,我们被迫发送所有参数,并且可选参数需要作为 NULL 发送。

我们可以通过提供带有必需参数的构造函数,然后提供不同的 setter 方法来设置可选参数来解决参数过多的问题。这种方法的问题是,代码可读性会非常差,而且很容易引入错误。 构建器模式通过提供一种 逐步构建对象的方法 来解决这些的问题。

三. 代码案例

看这个案例前可以先去看看我的写的这篇工厂模式文章,我是根据里面的案例进行优化的

当一个类构造器需要传入很多参数时,如果创建这个类的实例,代码可读性会非常差,而且很容易引入错误,比如以下代码,创建一台没有喇叭 的pc电脑,就要在后面输入null,而且这个参数是必须要输入的

        Computer pc = ComputerFactory.getComputer("pc", "17 GB", "1 TB",null);

可以通过建造者模式优化以上问题,我设计了如下示意图:

image-20240226230811065

让我们看看如何在 这个案例 中实现建造者设计模式解决问题。

3.1 创建ComputerBuilder 类

这个类是通过建造者模式去设计的,我们可以通过这个类去构造computer对象

/*** 电脑对象** @author chenyunzhi* @date 2024/2/25 21:49*/
public class ComputerBuilder extends Computer{private final String memory;private final String disk;private final Boolean isSpeaker;/*** 私有构造函数 以 Builder 类作为参数*/private ComputerBuilder(Builder builder) {this.memory = builder.memory;this.disk = builder.disk;this.isSpeaker = builder.isSpeaker;}public static class Builder {private final String memory;private final String disk;private Boolean isSpeaker;public Builder(String memory, String disk) {this.memory = memory;this.disk = disk;}public Builder setIsSpeaker(Boolean isSpeaker) {this.isSpeaker = isSpeaker;return this;}/*** 返回客户端程序所需的对象*/public Computer build() {return new ComputerBuilder(this);}}@Overridepublic String memory() {return this.memory;}@Overridepublic String disk() {return this.disk;}@Overridepublic Boolean isSpeaker() {return this.isSpeaker;}
}

代码解析:

  1. 首先,我们需要创建一个 ComputerBuilder 类 ,里面有Computer 的所有参数,然后在 ComputerBuilder 类 中创建一个 静态嵌套类 Builder ,然后将所有参数从外部类复制到 Builder 类

  2. 在 Builder 类中创建一个 公共的 构造函数,并将所有必需的属性作为参数。

  3. 在Builder 类 中 设置可选参数 isSpeaker 的方法,并且在设置可选属性后应该返回相同的 Builder 对象。

  4. 最后一步是在 Builder 类中提供一个build()方法,该方法将返回客户端程序所需的对象。为此,我们需要在类中有一个私有构造函数,并以 Builder 类作为参数。

3.2 修改子类

之前我们是通过传入指定参数方式,现在修改成 传入Computer 对象

public class Laptop extends Computer {private final String memory;private final  String disk;private  Boolean isSpeaker;public Laptop(Computer computer) {this.memory = computer.memory();this.disk = computer.disk();this.isSpeaker = computer.isSpeaker();}@Overridepublic String memory() {return this.memory;}@Overridepublic String disk() {return this.disk;}@Overridepublic Boolean isSpeaker() {return this.isSpeaker;}
}

pc

public class Pc extends Computer {private final String memory;private final String disk;private Boolean isSpeaker;public Pc(Computer computer) {this.memory = computer.memory();this.disk = computer.disk();this.isSpeaker = computer.isSpeaker();}@Overridepublic String memory() {return this.memory;}@Overridepublic String disk() {return this.disk;}@Overridepublic Boolean isSpeaker() {return this.isSpeaker;}
}

3.3 修改工厂

ComputerFactory

    public static Computer getComputer(String type, Computer computer) {if (PC.equals(type)) {return new Laptop(computer);} else if (LAPTOP.equals(type)) {return new Pc(computer);} else {return null;}}

3.4 测试

public class Test
{public static void main(String[] args) {Computer laptop = ComputerFactory.getComputer("laptop",new ComputerBuilder.Builder("17 GB", "1TB").setIsSpeaker(true).build());Computer pc = ComputerFactory.getComputer("pc",new ComputerBuilder.Builder("17 GB", "1TB").build());System.out.println("pc电脑 = " + pc);System.out.printf("laptop电脑 = " + laptop);}
}

image-20240226234638623

四. 建造者模式案例

Java 类中的一些构建器模式示例是:

  • java.lang.StringBuilder#append()(不同步)
  • java.lang.StringBuffer#append() (同步)

通过调用append方法,我们可以逐步构建字符串,最终通过toString方法获得最终的表示。

这就是 java 中构建器设计模式的全部内容。

作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498067.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EAP-TLS实验之Ubuntu20.04环境搭建配置(FreeRADIUS3.0)(四)

该篇主要介绍了利用配置ca.cnf、server.cnf、client.cnf在certs路径下生成证书文件(非执行bootstrap脚本,网上也有很多直接通过openssl命令方式生成的文章),主要参考(概括中心思想)官方手册,以及…

高校物品捐赠管理系统|基于springboot高校物品捐赠管理系统设计与实现(源码+数据库+文档)

高校物品捐赠管理系统目录 目录 基于springboot高校物品捐赠管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、捐赠信息管理 3、论坛信息管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算…

基于springboot+vue的新冠病毒密接者跟踪系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

使用 Haproxy 搭建Web群集

Haproxy是目前比较流行的一种群集调度工具,同类群集调度工具有很多,如LVS 和Nginx。相比较而言,LVS.牲能最好.但是搭建相对复杂:Nginx的upstream模块支持群集功能.但是对群集节点健康检查功能不强,性能没有…

QT Mingw编译ffmpeg源码以及测试

文章目录 前言下载msys2ysamFFmpeg 搭建编译环境安装msys2安装QT Mingw编译器到msys环境中安装ysam测试 编译FFmpeg 前言 FFmpeg不像VLC有支持QT的库文件,它仅提供源码,需要使用者自行编译成对应的库,当使用QTFFmpeg实现播放视频以及视频流时…

界面控件DevExpress WinForms 2024产品路线图预览(一)

DevExpress WinForm拥有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任…

Constructor构造方法

在我们创建实例时,我们经常需要同时初始化这个实例,例如: Person ming new Person(); ming.setName("卫什么"); ming.setAge("18"); 这样需要三行代码,实际上,在我们创建实例时,是通过…

网络热门项目:任务悬赏。了解任务悬赏系统的功能,支持搭建同款系统运营项目。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 任务悬赏项目:我们在刷短视频的时候就会发现很多博主去推广那些小游戏&a…

Carla自动驾驶仿真八:两种查找CARLA地图坐标点的方法

文章目录 前言一、通过Spectator获取坐标二、通过道路ID获取坐标总结 前言 CARLA没有直接的方法给使用者查找地图坐标点来生成车辆,这里推荐两种实用的方法在特定的地方生成车辆。 一、通过Spectator获取坐标 1、Spectator(观察者)&#xf…

金三银四面试必问:Redis真的是单线程吗?

文章目录 01 Redis中的多线程1)redis-server:2)jemalloc_bg_thd3)bio_xxx: 02 I/O多线程03 Redis中的多进程04 结论▼延伸阅读 由面试题“Redis是否为单线程”引发的思考 作者:李乐 来源:IT阅读…

groovy:XmlParser 读 Freeplane.mm文件,生成测试案例.csv文件

Freeplane 是一款基于 Java 的开源软件,继承 Freemind 的思维导图工具软件,它扩展了知识管理功能,在 Freemind 上增加了一些额外的功能,比如数学公式、节点属性面板等。 强大的节点功能,不仅仅节点的种类很多&#xff…

Jmeter 安装

JMeter是Java的框架,因此在安装Jmeter前需要先安装JDK,此处安装以Windows版为例 1. 安装jdk:Java Downloads | Oracle 安装完成后设置环境变量 将环境变量JAVA_HOME设置为 C:\Program Files\Java\jdk1.7.0_25 在系统变量Path中添加 C:\Pro…