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

文章目录

  • 一. 使用场景
  • 二. 具体实现
  • 三. 小结
    • 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/871817.shtml

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

相关文章

2024-07-15 Unity插件 Odin Inspector4 —— Collection Attributes

文章目录 1 说明2 集合相关特性2.1 DictionaryDrawerSettings2.2 ListDrawerSettings2.3 TableColumnWidth2.4 TableList2.5 TableMatrix 1 说明 ​ 本章介绍 Odin Inspector 插件中集合&#xff08;Dictionary、List&#xff09;相关特性的使用方法。 2 集合相关特性 2.1 D…

2-34 小波神经网络采用传统 BP 算法

小波神经网络采用传统 BP 算法&#xff0c;存在收敛速度慢和易陷入局部极小值两个突出弱点。建立了基于遗传算法的小波神经网络股票预测模型 GA-WNN。该模型结合了遗传算法的全局优化搜索能力以及小波神经网络良好的时频局部特性。运用 MATLAB 对拟合和预测过程进行仿真。结果表…

<数据集>绝缘子缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;2139张 标注数量(xml文件个数)&#xff1a;2139 标注数量(txt文件个数)&#xff1a;2139 标注类别数&#xff1a;8 标注类别名称&#xff1a;[insulator, broken disc, pollution-flashover, Two glass, Glassdirt…

李笑来思考框架的结晶《思考的真相》(2024 年新书)

点开文章的你肯定读过李笑来的书&#xff0c;比如讲认知的《财富自由之路》、讲管理自己的《把时间当做朋友》、讲财富底层逻辑的《财富的真相》、讲定投的《让时间陪你慢慢变富》等等。 李笑来的书不讲究华丽的文字&#xff0c;在意逻辑、论证的严谨&#xff0c;层层递进&…

数据结构之通过“ 队列 ”实现的“ 栈 ”功能。

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;数据结构 前言 本节内容是利用“ 队列 ”先进先出的特点 实现 “ 栈 ” 先进后出。 一、题目 1.1 题目描述&#xff1a; 请你仅使用两个队列实现一个后入先出&…

成为CMake砖家(1): 在Windows上查看CMake文档

大家好&#xff0c;我是白鱼。 在使用 CMake 的过程中&#xff0c;想必有不少朋友像我一样&#xff0c; 想在本地查看 CMake 文档。 首先安装 CMake, Installer 版本&#xff1a; 安装后&#xff0c;从开始菜单输入 CMake&#xff0c; 选择结果中的 “CMake Documentation”…

如何在 Shell 脚本中使用函数 ?

函数是一个可重用的代码块。我们经常把重复的代码放入一个函数中&#xff0c;并从不同的地方调用该函数&#xff0c;库是函数的集合。我们可以在库中定义常用的函数&#xff0c;其他脚本可以使用它们而无需复制代码。 Calling function 在 Shell 中&#xff0c;调用函数和调用…

CSS 选择器:精通网页样式的基础

CSS 选择器&#xff1a;精通网页样式的基础 CSS&#xff08;层叠样式表&#xff09;是网页设计中不可或缺的一部分&#xff0c;它用于控制网页元素的布局和外观。CSS 选择器是其中的核心概念&#xff0c;它允许开发者精确地指定要应用样式的 HTML 元素。本文将深入探讨 CSS 选…

1.33、激活可视化卷积神经网络(matalb)

1、激活可视化卷积神经网络原理及流程 激活可视化&#xff08;Activation Visualization&#xff09;指的是通过可视化神经网络中激活函数的输出&#xff0c;来理解神经网络是如何学习并提取特征的过程。在卷积神经网络&#xff08;CNN&#xff09;中&#xff0c;我们可以通过…

tomcat的优化、动静分离

tomcat的优化 tomcat自身的优化 tomcat的并发处理能力不强&#xff0c;大项目不适应tomcat做为转发动态的中间件&#xff08;k8s集群&#xff0c;pytnon rubby&#xff09;&#xff0c;小项目会使用&#xff08;内部使用的&#xff09;动静分离 默认配置不适合生产环境&…

MySQl高级篇 -索引优化篇

索引 InnoDB采用了一个B数来存储索引&#xff0c;使得在千万级数据量的一个情况下&#xff0c;树的高度可以控制在3层以内&#xff0c;而层高代表磁盘IO的一个次数&#xff0c;因此基于索引查找可以减少磁盘IO的次数 MySQL的索引是在存储引擎层实现的&#xff0c;不同的存储引…

测试面试宝典(六)—— 请回答集成测试和系统测试的区别,以及它们的应用场景主要是什么?

一、集成测试和系统测试的区别 &#xff08;一&#xff09;测试的目的 • 集成测试&#xff1a;主要目的是验证各个模块组合在一起后&#xff0c;它们之间的接口和交互是否正确&#xff0c;是否能够按照设计要求协同工作&#xff0c;以确保系统的稳定性和可靠性&#xff0c;重…

头歌资源库(31)象棋中马遍历棋盘的问题

一、 问题描述 二、算法思想 这是一个典型的深度优先搜索问题。 首先&#xff0c;我们创建一个mn的棋盘&#xff0c;并初始化所有的点为未访问状态。 然后&#xff0c;我们从(0, 0)位置开始进行深度优先搜索。 在每一步中&#xff0c;我们先标记当前位置为已访问&#xff0…

力扣 hot100 -- 多维动态规划

&#x1f447;woc&#xff0c;这不是最熟悉那种&#xff0c;记忆化 dfs 或者 普通的深度优先搜索&#xff1f;&#xff1f;都适用于二维地图&#x1f447; DFS&#xff08;深度优先搜索&#xff09;8种题型_dfs典型问题-CSDN博客 目录 &#x1f943;不同路径 &#x1f33c;最…

Android Viewpager2 remove fragmen不生效解决方案

一、介绍 在如今的开发过程只&#xff0c;内容变化已多单一的fragment&#xff0c;变成连续的&#xff0c;特别是以短视频或者直播为主的场景很多。从早起的Viewpage只能横向滑动&#xff0c;到如今的viewpage2可以支持横向或者竖向滑动。由于viewpage2的adapter在设计时支持缓…

解决mysql,Navicat for MySQL,IntelliJ IDEA之间中文乱码

使用软件版本 jdk-8u171-windows-x64 ideaIU-2021.1.3 mysql-essential-5.0.87-win32 navicat8_mysql_cs 这个问题我调试了好久&#xff0c;网上的方法基本上都试过了&#xff0c;终于是解决了。 三个地方结果都不一样。 方法一 首先大家可以尝试下面这种方法&#xff1a…

基于Python+Django+MySQL+Echarts的租房数据可视化分析系统

租房数据可视化 DjangoMySQLEcharts 基于PythonDjangoMySQLEcharts的租房数据可视化分析系统 Echarts 信息存储在数据库中 不含爬虫代码&#xff0c;或爬虫代码已失效 不支持登录注册 简介 基于DjangoMySQLEcharts的租房数据可视化系统通过连接数据库获取数据&#xff0c…

【格密码基础】旋转格的性质

目录 一. 回顾ZSVP问题 二. 基于ZSVP问题的密码系统 三. 格基旋转与Gram矩阵 四. 补充矩阵QR分解 4.1 矩阵分解 4.2 举例 前序文章请参考&#xff1a; 【格密码基础】详解ZSVP问题-CSDN博客 一. 回顾ZSVP问题 根据之前的讨论我们知道解决ZSVP问题的计算复杂度为&#x…

C++ 入门09:友元函数和友元类

往期回顾&#xff1a; C 入门06&#xff1a;类的进阶&#xff08;构造函数的重载与拷贝构造函数&#xff09;-CSDN博客 C 入门07&#xff1a;静态成员和常量成员-CSDN博客 C 入门08&#xff1a;运算符重载-CSDN博客 一、前言 在前面文章的学习中&#xff0c;我们了解了类和对象…

一款IM即时通讯聊天系统源码,包含app和后台源码

一款IM即时通讯聊天系统源码 聊天APP 附APP&#xff0c;后端是基于spring boot开发的。 这是一款独立服务器部署的即时通讯解决方案&#xff0c;可以帮助你快速拥有一套自己的移动社交、 企业办公、多功能业务产品。可以 独立部署&#xff01;加密通道&#xff01;牢牢掌握通…