【设计模式之美】【建造型】建造者模式:处理复杂成员变量以及它们之间的关系

文章目录

  • 一. 使用场景
  • 二. 具体实现
  • 三. 小结
    • 1. 结合场景使用
    • 2. 与工厂模式的区别

建造者模式本身不难,重点是掌握好它的适用场景。

一. 使用场景

如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和易用性,我们可以通过构造函数配合 set() 方法来解决。

但是,如果存在下面情况中的任意一种,我们就要考虑使用建造者模式了。

  • 如果创建对象时必填的属性有很多,那构造函数就会出现参数列表很长的问题。此时我们也无法通过set方法设置必填属性,因为没有设置的必填属性无法判断。
  • 如果类的属性之间有一定的依赖关系或者约束条件,我们继续使用构造函数配合 set() 方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。
  • 如果我们希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,此时我们就不能在类中暴露 set() 方法。

接下来看建造者模式是如何解决这些问题的。

 

二. 具体实现

对于校验与属性之间存在关系:

我们可以把校验逻辑放置到 Builder 类中,先创建建造者,并且通过 set() 方法设置建造者的变量值,然后在使用 build() 方法真正创建对象之前,做集中的校验,校验通过之后才会创建对象。

对于不可变对象:

把类的构造函数改为 private,这样就只能通过建造者来创建对象。另外不提供提供任何 set() 方法,这样创建出来的对象就是不可变对象了。

具体的代码如下所示:

public class ResourcePoolConfig {private String name;private int maxTotal;private int maxIdle;private int minIdle;private ResourcePoolConfig(Builder builder) {this.name = builder.name;this.maxTotal = builder.maxTotal;this.maxIdle = builder.maxIdle;this.minIdle = builder.minIdle;}//...省略getter方法...//我们将Builder类设计成了ResourcePoolConfig的内部类。//我们也可以将Builder类设计成独立的非内部类ResourcePoolConfigBuilder。public static class Builder {private static final int DEFAULT_MAX_TOTAL = 8;private static final int DEFAULT_MAX_IDLE = 8;private static final int DEFAULT_MIN_IDLE = 0;private String name;private int maxTotal = DEFAULT_MAX_TOTAL;private int maxIdle = DEFAULT_MAX_IDLE;private int minIdle = DEFAULT_MIN_IDLE;public ResourcePoolConfig build() {// 校验逻辑放到这里来做,包括必填项校验、依赖关系校验、约束条件校验等if (StringUtils.isBlank(name)) {throw new IllegalArgumentException("...");}if (maxIdle > maxTotal) {throw new IllegalArgumentException("...");}if (minIdle > maxTotal || minIdle > maxIdle) {throw new IllegalArgumentException("...");}return new ResourcePoolConfig(this);}public Builder setName(String name) {if (StringUtils.isBlank(name)) {throw new IllegalArgumentException("...");}this.name = name;return this;}public Builder setMaxTotal(int maxTotal) {if (maxTotal <= 0) {throw new IllegalArgumentException("...");}this.maxTotal = maxTotal;return this;}public Builder setMaxIdle(int maxIdle) {if (maxIdle < 0) {throw new IllegalArgumentException("...");}this.maxIdle = maxIdle;return this;}public Builder setMinIdle(int minIdle) {if (minIdle < 0) {throw new IllegalArgumentException("...");}this.minIdle = minIdle;return this;}}
}//通过内部类builder来创建对象,build的时候会校验属性并创建对象。
ResourcePoolConfig config = new ResourcePoolConfig.Builder().setName("dbconnectionpool").setMaxTotal(16).setMaxIdle(10).setMinIdle(12).build();
// 这段代码会抛出IllegalArgumentException,因为minIdle>maxIdle

 

三. 小结

1. 结合场景使用

如果对象只是用来映射数据库读出来的数据,那我们直接暴露 set() 方法来设置类的成员变量值是完全没问题的。并且,使用建造者模式来构建对象,代码实际上是有点重复的,ResourcePoolConfig 类中的成员变量,要在 Builder 类中重新再定义一遍。

所以选择建造者模式,需要结合具体的实际场景来使用。

 

2. 与工厂模式的区别

  • 工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。
  • 建造者模式是用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

 

参考:
王争:《设计模式之美》

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

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

相关文章

Python Linux环境(Centos8)安装minicoda3+jupyterlab

文章目录 安装miniconda安装python环境启动 最近服务器检查&#xff0c;我下面的服务器有漏洞&#xff0c;不得已重装了&#xff0c;正好记录下怎么从零到python写代码。 安装miniconda miniconda是anconda的精简版&#xff0c;就是管理python环境的得力助手。 # 创建一个名…

C语言 do while循环语句练习 下

猜数字游戏实现 //猜数字游戏 //电脑产生 一个随机数&#xff08;1-100) //猜数字 //猜大了 //猜小了 //直到猜对了&#xff0c;结束 #include <stdlib.h> #include <time.h> void menu() {printf("********************************\n");printf("…

【Redis7】高阶篇

1 Redis单线程 VS 多线程(入门篇) 1.1 面试题 redis到底是单线程还是多线程&#xff1f; IO多路复用听说过吗&#xff1f; redis为什么快&#xff1f; 1.2 Redis为什么选择单线程&#xff1f; 1.2.1 是什么 这种问法其实并不严谨&#xff0c;为啥这么说呢? Redis的版本…

怎么将图片插入excel单元格中

首先选中单元格选择插入 在图片位置选择插入图片的位置 然后就插入成功了&#xff0c;一开始会觉得图片是附在表格上面的&#xff0c;并不在单元格里面&#xff0c;但是右边有一个小图片的图标&#xff0c;点击它可以缩小到单元格里面&#xff0c;再点击就是放大&#xff1b;

【无人值守】对数据中心电力分配系统发展的影响

数据中心在现代信息发展中承载着巨量数据的计算、存储、挖掘、分析和应用等多个方面的功能&#xff0c;是国计民生各行业的多样化的信息化的资产。对稳定的运行与安全运维是基本需求也是重要的保障。 数据中心属于高能耗产业&#xff0c;对用电负荷大且要求极度稳定。除了对电力…

ROS、pix4、gazebo、qgc仿真ubuntu20.04

一、ubuntu、ros安装教程比较多&#xff0c;此文章不做详细讲解。该文章基于ubuntu20.04系统。 pix4参考地址&#xff1a;https://docs.px4.io/main/zh/index.html 二、安装pix4 1. git clone https://github.com/PX4/PX4-Autopilot.git --recursive 2. bash ./PX4-Autopilot…

华为od 100问 持续分享4-目标院校及分数线

我是一名软件开发培训机构老师&#xff0c;我的学生已经有上百人通过了华为OD机试&#xff0c;学生们每次考完试&#xff0c;会把题目拿出来一起交流分享。 重要&#xff1a;2024年5月份开始&#xff0c;考的都是OD统一考试&#xff08;D卷&#xff09;&#xff0c;题库已经整…

TikTok账号矩阵运营怎么做?

这几年&#xff0c;聊到出海避不过海外抖音&#xff0c;也就是TikTok&#xff0c;聊到TikTok电商直播就离不开账号矩阵&#xff1b; 在TikTok上&#xff0c;矩阵养号已经成为了出海电商人的流行策略&#xff0c;归根结底还是因为矩阵养号可以用最小的力&#xff0c;获得更大的…

图片转换为张量

将一张图片转换为张量可以通过使用 Python 的图像处理库&#xff08;如 PIL 或 OpenCV&#xff09;结合 PyTorch 的工具函数来实现。下面我将分别展示如何使用 PIL 和 OpenCV 来加载和转换图片为 PyTorch 张量。 使用 PIL 加载和转换图片为张量 首先&#xff0c;使用 PIL 库加…

RTI DDS大数据碎片

有两种类型的碎片&#xff1a;IP级碎片和DDS级碎片。 当传输层&#xff08;通常是UDP或TCP&#xff09;提供的有效载荷超过适合链路帧的最大有效载荷大小&#xff08;也称为链路最大传输单元或链路MTU&#xff09;时&#xff0c;就会发生IP级碎片。如果网络是以太网&#xff0…

Java中使用代理IP的詳細教程

在Java中&#xff0c;如何使用代理IP呢&#xff1f;本文將從原理和實現方法&#xff0c;詳細介紹Java中使用代理IP的技巧。 代理IP的原理 代理IP可以分為多種類型&#xff0c;包括HTTP代理、HTTPS代理和Socks代理等。每種代理都有不同的應用場景和優缺點。 HTTP代理&#xf…

【大模型】FAISS向量数据库记录:从基础搭建到实战操作

文章目录 文章简介Embedding模型BGE-M3 模型亮点 FAISS是什么FAISS实战安装faiss加载Embedding模型创建FAISS数据库搜索FAISS数据删除FAISS数据保存、加载FAISS索引 总结 本人数据分析领域的从业者&#xff0c;拥有专业背景和能力&#xff0c;可以为您的数据采集、数据挖掘和数…

测试技术相关

介绍一下cookie&#xff0c;session和toke的区别 session存储于服务器&#xff0c;可以理解为一个状态列表&#xff0c;拥有一个唯一识别符号se5sionld&#xff0c;通常存放于cookie中。 服务器收到cookie后解析出sessionld&#xff0c;再去session列表中查找&#xff0c;才能找…

X86架构和ARM架构的区别

X86架构和ARM架构是两种常见的微处理器架构&#xff0c;主要用于个人电脑、服务器和移动设备等。 历史和起源&#xff1a;X86起源于Intel的8086/8088芯片&#xff0c;广泛应用于IBM PC系列&#xff1b;而ARM由Advanced RISC Machines&#xff08;ARM公司&#xff09;设计&…

通用图形处理器设计GPGPU基础与架构(二)

一、前言 本系列旨在介绍通用图形处理器设计GPGPU的基础与架构&#xff0c;因此在介绍GPGPU具体架构之前&#xff0c;需要了解GPGPU的编程模型&#xff0c;了解软件层面是怎么做到并行的&#xff0c;硬件层面又要怎么配合软件&#xff0c;乃至定出合适的架构来实现软硬件协同。…

url拼接,本人自用

/*** Description: 用来处理水务专题-辅料管理接口中&#xff0c;url的拼接* Description: 拼接String类型的数据* Date: 2024/06/21* return: java.lang.String* param: [url, parameterName, parameterValue]**/ public String appendParameterToURL(String url, String para…

15- 微分方程

对三角函数不敏感

Linux - 基础开发工具(yum、vim、gcc、g++、make/Makefile、git、gdb)

目录 Linux软件包管理器 - yum Linux下安装软件的方式 认识yum 查找软件包 安装软件 如何实现本地机器和云服务器之间的文件互传 卸载软件 Linux编辑器 - vim vim的基本概念 vim下各模式的切换 vim命令模式各命令汇总 vim底行模式各命令汇总 vim的简单配置 Linux编译器 - gc…

提高记忆力7种自然(高效)的方法

你的记忆力如何?你的认知功能是否如你所希望的那样强大? 如果没有,那么你肯定会对将在本文中与你分享的记忆改善技巧感兴趣的。 不管你怎么想,或者别人怎么说,提高你记忆信息的能力是完全有可能的。只要知道正确的方法即可。(别担心,你并不需要做出任何重大的生活方式改…

10 个 OKR 提示将改变您执行 OKR 的方式

我们都喜欢好的表情包&#xff0c;因为它们很有趣&#xff0c;可以分享&#xff0c;非常适合与同事们一起开怀大笑。表情包可以为工作场所带来一种友情和轻松的感觉&#xff0c;从而建立一种健康的团队文化&#xff0c;这一点很重要。然而&#xff0c;我们都知道它们也会分散注…