设计模式导读:建造者模式的细腻之处与编程技巧

笔者的碎碎念

其实之前有写过建造者模式的文章,但是感觉其实写的不怎么样,而且自己也理解的一般,但是阅读一些框架源码发现,这些模式真的蛮重要的,很多框架例如OkHttpRetrofit等等都大量使用了建造者模式以及一些其他的设计模式,于是决定对这些模式进行学习和整理,将写一个专栏来记录自己的的学习记录,你知道的,好记性不如烂笔头,加油!

建造者模式的由来

因 Java 中没有命名参数的概念,当一个类的构造器可选参数太多的时候,代码可读性会变得很差。我们通过一个例子来说明,假设我们有一个连接池的配置类 ConnectionPoolConfig,它包含了多个可选参数,比如 maxConnections(最大连接数)、minConnections(最小连接数)、timeout(超时时间)等。为了支持不同的配置选项,最初可能会使用伸缩式构造器模式或者JavaBeans构造器模式来创建这个对象。

伸缩式构造器模式

public class ConnectionPoolConfig {private int maxConnections;private int minConnections;private int timeout;public ConnectionPoolConfig(int maxConnections, int minConnections, int timeout) {this.maxConnections = maxConnections;this.minConnections = minConnections;this.timeout = timeout;}
...省略ConnectionPoolConfig中的其他构造方法// Getters and setters
}

使用伸缩式构造器模式,我们可能会遇到以下问题:

  • 参数顺序依赖性: 如果某些参数是可选的,并且它们的顺序与构造函数中的参数顺序不匹配,那么我们就不得不在构造对象时填充未使用的默认值,比如:

    ConnectionPoolConfig config = new ConnectionPoolConfig(10, 5, 0); // timeout 默认为 0
    
  • 参数类型相似性: 如果两个参数类型相似(比如都是整数),在构造对象时容易搞错参数的顺序,这可能会导致严重的错误。

JavaBeans构造器模式

然后,我们针对这些进行改进,有了后来的JavaBeans构造器模式。

public class ConnectionPoolConfig {private int maxConnections;private int minConnections;private int timeout;public ConnectionPoolConfig() {// Empty constructor}// Setterspublic void setMaxConnections(int maxConnections) {this.maxConnections = maxConnections;}public void setMinConnections(int minConnections) {this.minConnections = minConnections;}public void setTimeout(int timeout) {this.timeout = timeout;}
...省略// Getters
}

使用JavaBeans构造器模式,虽然解决了参数顺序依赖性的问题,但引入了新的问题: 

  • 对象状态不一致性: 构建对象需要多次调用不同的 setter 方法,这可能会导致对象在构造过程中处于不一致的状态。例如,如果某个字段在设置之前被访问,可能得到不完整或不正确的对象状态。 

建造者模式

于是,建造者模式(Builder Pattern)应运而生。

建造者模式在这些问题的基础上提供了更加灵活和安全的对象构建方式:

public class ConnectionPoolConfig {private final int maxConnections;private final int minConnections;private final int timeout;private ConnectionPoolConfig(Builder builder) {this.maxConnections = builder.maxConnections;this.minConnections = builder.minConnections;this.timeout = builder.timeout;}// Getterspublic static class Builder {private int maxConnections;private int minConnections;private int timeout;public Builder() {// 默认值或者空构造器}public Builder maxConnections(int maxConnections) {this.maxConnections = maxConnections;return this;}public Builder minConnections(int minConnections) {this.minConnections = minConnections;return this;}public Builder timeout(int timeout) {this.timeout = timeout;return this;}public ConnectionPoolConfig build() {return new ConnectionPoolConfig(this);}}
}

优点: 

  • 链式调用: 使用建造者模式,可以使用链式调用来设置对象的各个属性,清晰地表达出构建对象的步骤和顺序。
ConnectionPoolConfig config = new ConnectionPoolConfig.Builder().maxConnections(10).minConnections(5).timeout(0).build();

  • 对象不可变性: 在建造者模式中,可以将对象设计为不可变的(Immutable),一旦构建完成后,对象的状态不可修改,保证了对象的线程安全性和一致性。
  • 消除对象状态不一致性问题: 建造者模式通过在最终构建之前保持对象状态的一致性,避免了JavaBeans模式中可能出现的对象状态不一致性问题。
  • 易于解耦:将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。
  • 易于精确控制对象的创建:将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
  • 易于拓展:增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。

每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。 

模式原理

使用场景 

建造者模式适用于需要创建复杂对象(对象有多个部分,且构建过程复杂)的场景,或者需要创建多个相似对象(只有部分属性不同)的场景。它有效地解决了伸缩式构造器模式和JavaBeans构造器模式存在的问题,并提供了一种更加优雅和灵活的解决方案。你经常能在Android看到一些常见的技术框架中都使用了该模式,例如OkHttp框架中就有它的大量使用。关于OkHttp我也有文章进行分析,如果你感兴趣,可以去看看OkHttp中是如何使用建造者模式的->【传送门】。

使用 

  1. 构造者的创建:客户端通过创建一个具体的建造者对象(如 Builder),并使用链式调用来设置产品的各个属性
     

    ConnectionPoolConfig config = new ConnectionPoolConfig.Builder().maxConnections(10).minConnections(5).timeout(30).build();
    
  2. 属性设置

    每次调用建造者的设置方法(如 maxConnectionsminConnectionstimeout)时,建造者内部会更新自己的状态,以便在构建最终产品时使用。
  3. 构建产品

    最终调用 build() 方法时,建造者将使用其内部状态来实例化并初始化产品对象 ConnectionPoolConfig,并返回给客户端。

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

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

相关文章

人脸处理——人脸换脸基础算法探索与应用测试指南

人工智能(AI)彻底改变了我们生活的许多方面,而这项技术的应用之一就是AI换脸工具。这些工具使用先进的计算机视觉技术和深度学习算法,例如生成对抗网络 (GAN),在照片或视频中将一个人的脸与另一个人的脸交换。 1. Dee…

Java简易仓管系统

java import java.sql.*; import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSource; import java.util.*;// 商品类 class Product {private String name;private int quantity;public Product(String name, int quantity) {this.name name;this.quant…

无废话版的TypeScript(TS)教程可以满足日常项目使用

中文官网 在中文网(官网也可以)点击立即试用->在浏览器中运行->在这里可以演示本篇博客内的内容 在这个页面右边点击js就是ts编译后的js内容,也可以点击左上角进行版本设置和一些配置,这个看个人意愿,我本人打开网站直接用了 类型推断 不加类型时,TS会进行类型推断,以…

源代码防泄密如何做?10种方法教你源代码防泄密

企业如何正确做好源代码防泄密工作?推荐10种方法教你源代码防泄密。1. 使用加密技术 强加密算法:使用AES、RSA等强加密算法对源代码进行加密,确保只有授权用户才能解密和访问源代码。 2. 代码混淆 混淆工具:使用ProGuard、Obfusc…

Ubuntu使用cat替代vim编写文件

docker创建容器&#xff0c;进入容器之后无法使用vi&#xff0c;vim&#xff0c;gedit apt update时报错&#xff0c;无法安装指令&#xff0c;sources.list无法编辑 使用cat编辑文件 rootabcd:/# cat >文件名 << EOF > 内容 > EOF编写文件时加上EOF&#xff0c…

六西格玛培训公司:解锁成功之门,让企业与个人共赴“嗨”途

在竞争激烈的21世纪&#xff0c;六西格玛培训公司手握一把神奇的钥匙&#xff0c;帮助企业及个人轻松开启成功的大门。 对企业来说&#xff1a; 产品质量飞跃&#xff1a;不再是偶尔的精品&#xff0c;而是每个产品都如同精雕细琢的艺术品&#xff0c;吸引无数顾客争相购买。…

【Python】 异步编程

【Python】 异步编程 1. nest_asyncio基础定义2. nest_asyncio 举例实现基本用法 1. nest_asyncio基础定义 nest_asyncio.apply() 是 Python 编程中与异步编程相关的一个调用&#xff0c;它用于解决某些特定环境下的异步编程问题。下面是对这个调用的详细解释&#xff1a; nes…

【微信小程序 笔记】

协同工作和发布 - 协同工作 了解权限管理需求 在中大型的公司里&#xff0c;人员的分工非常仔细&#xff1a;同一个小程序项目&#xff0c;一般会有不同岗位、不同角色的员工同时参与设计与开发。 此时出于管理需要&#xff0c;我们迫切需要对不同岗位、不同角色的员工的权限进…

web3.0链游农民世界开发搭建0撸狼人杀玩法模式定制开发

随着区块链技术的飞速发展&#xff0c;Web3.0时代的链游已成为游戏行业的新宠。本文将介绍一款基于Web3.0的链游——农民世界&#xff0c;如何定制开发0撸狼人杀玩法模式&#xff0c;以及该模式的专业性、深度思考和逻辑性。 一、背景介绍 农民世界是一款以农业为主题的链游…

嵌入式系统基础

嵌入式系统基础主要包括以下几个方面&#xff1a; 1、定义&#xff1a; 嵌入式系统是以应用为中心&#xff0c;以计算机技术为基础&#xff0c;软硬件可裁剪&#xff0c;适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。它由硬件和软件组成&#xff0…

css 修改 input range 样式

这段必须要加上&#xff0c;清除默认样式,根据mdn文档介绍&#xff0c;这个样式兼容性不太好&#xff0c;应该多看看目标用户的浏览器支不支持。 -webkit-appearance: none; -moz-appearance: none; appearance: none; input[typerange]{-webkit-appearance: none;width:90px;h…

.NET 通过UserInit键实现Windows权限维持

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏&#xff0c;主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧&#xff0c;对内网和后渗透感兴趣的朋友们可以订阅该电子报刊&#xff0c;解锁更多的报刊内容。 02基本介绍 本文内容部分节选自小报童…

Spring Boot 学习第七天:动态代理机制与Spring AOP

1 概述 在Java的世界中&#xff0c;实现AOP的主流方式是采用动态代理机制&#xff0c;这点对于Spring AOP也一样。代理机制的主要目的就是为其他对象提供一种dialing以控制对当前对象的访问&#xff0c;用于消除或缓解直接访问对象带来的问题。通过这种手段&#xff0c;一个对象…

EEPROM与FLASH

一、EEPROM介绍 1.概念 EEPROM简介&#xff0c;EEPROM (Electrically Erasable Programmable read only memory)是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设备上擦除已有信息&#xff0c;重新编程。一般用在即插即用&…

【Bugku CTF】web解题记录

记录我在Bugku CTF靶场中做的比赛真题&#xff0c;便于自己以后的复习 1.my-first-sqli 进入此关卡&#xff0c;发现参数有username和password 我们尝试在username上注入数字型、字符型参数&#xff0c;后面发现注入字符型的单引号的有报错语句&#xff0c;我们在username上注…

【服务器08】之【游戏框架】之【加载主角】

首先简单了解一下帧率 FixedUpdate( ) > Update( ) > LateUpdate( ) 首先FixedUpdate的设置值 默认一秒运行50次 虽然默认是0.02秒&#xff0c;但FiexedUpdate并不是真的0.02秒调用一次&#xff0c;因为在脚本的生命周期内&#xff0c;FixedUpdate有一个小循环&…

大学计算机

项目一 了解计算机 1.1 了解计算机的诞生及发展阶段 1.2 认识计算机的特点、应用和分类 1&#xff0e;计算机的特点 1. 计算机的特点 2.计算机的应用 3.计算机的分类 4.数量单位 1.3 了解计算机操作系统的概念、功能与种类 1.操作系统概念 2.操作系统的作用 1&#xff0e…

主流的RAG框架

Rank1、LangChain(86k stars) https://github.com/langchain-ai/langchain/.当之无愧的霸主&#xff0c;范围很全面&#xff0c;但代码 Rank2、Quivr(33.4k stars) https://github.com/StanGirard/quivr Rank3、Llamalndex(32.1k stars) https://github.com/run-llama/llama…

MySQL数据库锁的实现原理

MySQL数据库的锁实现原理主要涉及到如何确保在多用户并发访问数据库时,保证数据的完整性和一致性。以下是MySQL数据库锁实现原理的详细解释: 锁的基本概念和目的 锁的概念:在数据库中,锁是用于管理对公共资源的并发控制的机制。当多个用户或事务试图同时访问或修改同一数…

Java零基础-集合:Set

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…