JS设计模式之“分即是合” - 建造者模式

image.png

引言

当我们在进行软件编程时,常常会遇到需要创建复杂对象的情况。这些对象可能有多个属性,属性之间存在依赖关系,或需要按照特定的骤来创建。在这种情况下,使用建造者模式Builder Pattern)可以提供一种活的方式来构建对象,避免对象构建过程的复杂性。

“分即是合” - 将对象的创建过程与其表示相互分离,但允许我们连续地构建对象逐步设置其属性,然后获取最终的构建结果

一. 什么是建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,旨在将对象的创建过程与其表示相互分离。它允许我们连续地构建对象逐步设置其属性,然后获取最终的构建结果。使用建造者模式,我们可以按照自己的需求构建对象,而不必关心对象的创建过程和内部细节。

fileOf7174.png

建造者模式通常包含以下几个角色:

  1. Director(导演):负责定义构建过程的顺序和逻辑,控制对象的创建过程。

  2. Builder(建造者):负责实际构建复杂对象的接口,定义了创建对象的每个步骤。

  3. ConcreteBuilder(具体建造者):实现 Builder 接口,实际进行对象的构建。

  4. Product(产品):表示最终构建完成的对象。

二. 深入建造者模式的神奇之处

案例场景一

fileOf7174.png

骑士对象

让我们通过一个简单的例子来说明建造者模式。假设我们正在开发一个游戏,需要构建一种特殊类型的角色:骑士。骑士有许多属性,包括名字等级武器盔甲等。为了构建骑士对象,我们可以使用建造者模式。

首先,我们定义一个角色类,用于表示骑士对象:

class Knight {constructor(name, level, weapon, armor) {this.name = name;this.level = level;this.weapon = weapon;this.armor = armor;}toString() {return `${this.name}, ${this.level}, weapon: ${this.weapon}, armor: ${this.armor}`;}
}

然后,我们定义一个骑士建造者类,用于逐步构建骑士对象:

class KnightBuilder {constructor() {this.name = null;this.level = null;this.weapon = null;this.armor = null;}// 名称setName(name) {this.name = name;return this;}// 等级setLevel(level) {this.level = level;return this;}// 武器setWeapon(weapon) {this.weapon = weapon;return this;}// 盔甲setArmor(armor) {this.armor = armor;return this;}// 构造骑士build() {return new Knight(this.name, this.level, this.weapon, this.armor);}
}

在这个例子,我们定义了一个KnightBuilder类它包含了与骑士对象相关的各种属性我们可以使用该建造者类逐步设置这些属性,终通过调用 build 方法来获取建完成的骑士对象。

接下来,让我们使用建造者模式来构建一个骑士对象:

const knight = new KnightBuilder().setName("Arthur").setLevel(10).setWeapon("Excalibur").setArmor("Plate").build();console.log(knight.toString());

在这个例子中,我们首先创建了一个 KnightBuilder 实例,并逐步设置了骑士对象的各个属性。最后,通过调用 build 方法,我们获取到了构建完成的骑士对象并打印出来。输出结果为:

Arthur, Level 10, weapon: Excalibur, armor: Plate

总结:

正如我们所看到的,通过建造者模式,我们可以在不污染对象类的情况下,方便地构建出具有各种属性的骑士对象。

案例场景二

fileOf7174.png

汽车对象

让我们继续通过一个汽车示例来加深对建造者式的使用。假设我们正在构建一个汽车对象,并且汽车具有一些复杂的属性。下面是一个简化的汽车建造者实现:

class Car {constructor() {this.brand = null;this.color = null;this.engine = null;}
}class CarBuilder {constructor() {this.car = new Car();}// 品牌setBrand(brand) {this.car.brand = brand;return this;}// 颜色setColor(color) {this.car.color = color;return this;}// 引擎setEngine(engine) {this.car.engine = engine;return this;}build() {return this.car;}
}// 创建汽车对象示例
const car = new CarBuilder().setBrand("Tesla").setColor("Red").setEngine("Electric").build();console.log(car);

在上面的示例中,我们有一个 Car 类表示汽车对象,包含了 brandcolorengine 等属性。然后,我们创建了一个 CarBuilder 类,用于逐步构建 Car 对象。CarBuilder 类中的各方法用于设置 Car 对象各个属性,并且每个方法都返回 CarBuilder 实例,以便可以进行链式调用。最后,通过调用 build 方法来返回最终 Car 对象。

以上的例子均展示了建造者模式的基本用法,我们可以根据实际情况,将建造者模式扩展到更复杂的情况,例如构建具有更多属性和复杂构建过程的对象。

三. 为什么要使用建造者模式

通过以上的实例我们可以总结使用建造者模式的优点:

  1. 灵活性高:建造者模式允许逐步构建复杂对象,并且可以根据需求自由选择和配置对象的属性,而不需要关心对象的创建过程和内部细节。

  2. 代码可读性好:通过将对象的构建过程封装在建造者类中,代码更加清晰直观。建造者模式提供了一种结构化的方式来创建对象,使得代码易于理解和维护

  3. 创建不可变对象:通过将对象的属性设置为私有,并提供相应的 getter 方法,可以确保对象在创建后不会被修改,增加对象的安全性和封装性。

  4. 代码复用性高:可以将复杂对象构建的逻辑封装在建造者类中,以便在同一场景下复用。

当然,任何一件事物并不是只有优点没有缺点,当然建造者模式也是有一定的缺点的。

  1. 增加代码量:引入建造者模式会增加一些额外的类和方法,这可能导致代码量的增加。有时候,如果只需要简单的对象,使用建造者模式可能会过于繁琐。

  2. 对象构建过程不够灵活:建造者模式在创建对象时要按照一定的顺序和一系列步骤。这可能会限制构建过程的灵活性,不够适应某些特殊情况。

  3. 可能存在建造者类过多:当对象有很多属性时,可能需要创建多个建造者类来构建对象。这可能会导致建造者类的增加,给代码的维护和理解带来一定的复杂性。

总结:

建造者模式适用于构建复杂的场景,特别当对象有多个属性、属性之有依赖关系或需要按照特定的顺序构建时。某些情况下,对象比较简单,使用建者模式可能会显得过于复杂和冗余。因此使用建造者模式需要权衡利弊,选择适合的设计模式。

四. 建造者模式和工厂模式的对比

JavaScript中的建造者模式和工厂模式在创建对象上有一些不同之处,下面是总结的一些对比。

对比方式

对比方式建造者模式工厂模式
目的和使用场景主要用于创建具有复杂属性和构建过程的对象。它可以逐步构建对象,并提供灵活的方法来设置对象的各个属性。适用于构建过程复杂,有多个步骤和可变参数的对象。主要用于根据不同的条件或参数创建不同类型的对象。它提供统一的接口来创建对象,只需要知道该接口而不用心具体的实现细节。
使用方式通过连续调用建造者类的方法来逐步构建对象最后通过获取构建结果的方法来获取最终的对象。通过调用工厂类的方法,传入相应参数或条件,工厂类根据传入的参数条件来创建相应的对象,并返回给客户端。
灵活性允许在构建对象时自由配置属性,并且可以选择性地属性。根据设置特定的属性,可以不设置某些属性适用于对象属性较多且有可选项的场景。工厂模式的创建逻辑相对固定,只需要传入相应的参数或条件,工厂类根据这些参数或条件来创建相应的对象。适用于对象创建不涉及复杂的逻辑判断,只是根据条件返回不同类型的对象。
代码复用可以将构建对象的逻辑封装在建造者中,可以不同的场景下复用相同的构建逻辑。将对象创建的逻辑封装在工厂中,可以根据不同的或参数创建不同的,从而实现代码的复用。

总结

综上所述,工厂模式和建造者模式都是用于创建对象的设计模式,他们在使用方式和灵活性上有一定的不同之处:

  • 工厂模式适用于创建不同类型的对象,根据条件或参数返回相应的对象,工厂模式主要关注对象的创建过程。

  • 建造者模式适用于创建具有复杂属性和构建过程的对象,建造者模式主要关注对象属性的设置和构建流程的控制。

小结

通过本文,我们了解到了JavaScript建造者模式的详细使用方式,最后我们在总结一下什么情况下我们会考虑使用建造者模式:

  1. 对象拥有复杂的属性:如果要创建的对象具有很多属性,而且这些属性之间存在一定的依赖关系或可选项,使用建造者模式可以提供更灵活的方式来构建对象,避免创建过程的复杂性。

  2. 构建过程具有多个步骤:如果对象的构建过程包含多个步骤,并且这些步骤可能因为不同的需求或条件而变化,使用建造者模式可以将构建过程分解为多个方法,并在其中逐步构建对象。

  3. 需要创建不可变对象:建造者模式可以通过将对象的属性设置为私有,并提供相应的 getter 方法,从而创建不可变对象。这样做可以保证对象的属性在创建后不会被修改,提高了对象的安全性和封装性。

  4. 需要代码的可读性和可维护性:使用建造者模式,可以将对象的构建过程、属性设置的逻辑都封装在建造者类中,这样可以使得代码更加清晰直观,易于理解和维护。

  5. 需要复用相同的构建逻辑:如果有多个场景需要使用相同的构建逻辑创建对象,可以将该构建逻辑抽象为一个建造者类,以便在不同的场景下复用同一份代码。

建造者模式适合用于构建具有复杂属性、多步骤构建过程、可配置性要求高的对象,并且需要提高代码的可读性和可维护性的情况下。通过使用建造者模式,可以简化对象的构建过程,有效地管理对象的属性和属性设置的逻辑。

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

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

相关文章

selenium启动总报错 WebDriverManager总是异常

我的环境用这个自动管理驱动的工具 WebDriverManager 总是报错 尝试过很多方法都没有,只好手动指定浏览器的位置 System.setProperty("webdriver.chrome.driver", "C:\\Users\\27224\\.cache\\selenium\\chromedriver\\win64\\128.0.6613.84\\chrome…

HTTP 协议详解

0x01:HTTP 协议简介 HTTP(HyperTextTransferProtocol,超文本传输协议),是一个工作在应用层的协议,它通常运行在 TCP 之上,它指定了客户端以什么样的格式发送信息,以及得到什么样的响…

uniapp微信小程序开发测试获取手机号码

先申请测试号 注意认证但是没有完全认证不要试测试号解密如下 总结我自己的两大坑 1.官网的WXBizDataCrypt需要导入crypto要提前下载但是试了很多次没有效果重新编写这个。将crypto库换成crypto-js库 2.我一直在尝试用下有下面这个界面的测试号不行获取不到用户的code还是啥忘记…

基于SpringBoot+Vue+MySQL的社区维修平台

系统背景 系统管理也都将通过计算机进行整体智能化操作,对于社区维修平台所牵扯的管理及数据保存都是非常多的,例如住户管理、社区公告管理、维修工管理、维修订单管理、接单信息管理、订单信息管理、在线沟通管理、举报信息管理、留言板管理、系统管理等…

记Spring HTTP Invoker远程调用的使用(二)基于Servlet方式,配置servlet映射url-pattern实现

目录 前言 一、概念 二、代码实现 1. 服务端实现 2. 客户端实现 前言 本篇接上一篇记Spring HTTP Invoker远程调用的使用(一)基于Url映射方式,DispatcherServlet统一处理实现-CSDN博客https://blog.csdn.net/u011529483/article/details/141…

搭建高可用OpenStack(Queen版)集群(九)之部署nova计算节点

一、搭建高可用OpenStack(Queen版)集群之部署计算节点 一、部署nova 1、安装nova-compute 在全部计算节点安装nova-compute服务 yum install python-openstackclient openstack-utils openstack-selinux -y yum install openstack-nova-compute -y 若yu…

【如何在MacOS升级ruby版本】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

OpenAI Whisper API (InvalidRequestError)

题意: OpenAI Whisper API(无效请求错误) 问题背景: Im trying to use OpenAI Whisper API to transcribe my audio files. When I run it by opening my local audio files from disk, it worked perfectly. Now Im developing a FastAPI e…

【超音速 专利 CN116109587A】一种复杂环境下密封钉焊缝质量检测方法

申请号CN202310066309.X公开号(公开)CN116109587A申请日2023.01.12申请人(公开)超音速人工智能科技股份有限公司(833753)发明人(公开)张俊峰(总); 陈炯标 原文摘要 本发明公开了一种复杂环境下密封钉焊缝…

如何在手机上设置国内代理IP地址:详细指南

在某些情况下,我们可能需要在手机上设置国内代理IP地址,以便访问特定的网络服务或提高网络连接的稳定性。本文将详细介绍如何在Android和iOS设备上设置代理IP地址。 在Android设备上设置代理IP地址 在Android设备上设置代理IP地址非常简单,只…

每日一练1:数字统计(含链接)

链接&#xff1a; [NOIP2010]数字统计_牛客题霸_牛客网 代码&#xff1a; #include <iostream> using namespace std;int main() {int a, b;int count 0;cin >> a >> b;for(int i a; a < b; a){i a;while(i>0){if(i%10 2) count;i / 10;}}cout…

asp.net Temporary ASP.NET Files修改为其他位置

Temporary ASP.NET Files这个文件夹是编译期间用于临时文件存储的目录。当请求一个新页面时ASP.NET会分析aspx页面并为其生成一个.cs文件&#xff0c;然后JIT编译器会编译这个cs生成一个dll&#xff0c;这些过程都是在这个目录里面进行的。其中还放了你在项目中引用的Assembly的…

线性代数|机器学习-P32循环矩阵的特征向量-傅里叶矩阵

文章目录 1. 大纲2. 循环矩阵2.1 移位矩阵P2.2 P的特征值和特征向量2.3 循环卷积矩阵2.4 循环卷积计算 3. 傅里叶矩阵 1. 大纲 循环矩阵在机器学习&#xff0c;图像处理中的应用循环卷积矩阵的特征值&#xff0c;特征向量&#xff0c;卷积规则循环卷积矩阵多项式表达&#xff…

小琳Python课堂:Python优先级队列深入解析:`PriorityQueue`类的使用与原理

小琳Python课堂开讲啦&#xff01;今天我们来深入解析Python中的PriorityQueue类&#xff0c;这个类在 多任务处理和数据优先级管理 中非常有用哦&#xff01;&#x1f31f; 在Python中&#xff0c;PriorityQueue类是queue模块的一部分&#xff0c;用于实现一个优先级队列。优先…

详解JavaScript

目录 JavaScript 引入样式 基础语法 变量 数据类型 运算符 JavaScript对象 数组 数组定义 数组操作 函数 语法格式 关于参数个数 函数表达式 对象 JQuery 语法 选择器 事件 常见的事件 操作元素 获取/设置元素内容 获取/设置元素属性 获取/设置CSS属性 …

【Spring Boot 3】【Web】返回图片

【Spring Boot 3】【Web】返回图片 背景介绍开发环境开发步骤及源码工程目录结构 背景 软件开发是一门实践性科学&#xff0c;对大多数人来说&#xff0c;学习一种新技术不是一开始就去深究其原理&#xff0c;而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中&a…

线性查找表的应用:用户登录注册程序

线性查找表是很简单的数据结构和算法。网站的用户登录注册时是基本的功能。本文首先给出线性查找表的基本实现&#xff0c;然后给出在用户登录注册的程序流程图&#xff0c;并将线性查找表应用到用户查询这一具体任务&#xff0c;并基于 Python 语言在控制台实现用户注册、登录…

【简单】 猿人学web第一届 第15题 备周则意怠,常见则不疑

数据接口分析 数据接口 https://match.yuanrenxue.cn/api/match/15 请求时需要携带 page 页码&#xff0c;m为加密参数 cookie中没有加密信息&#xff0c;携带 SessionId请求即可 加密参数还原 查看数据接口对应的 requests 栈 m参数 是通过 window.m() 方法执行后得到的 打上…

什么是 AWS CloudWatch?

AWS CloudWatch 是 AWS 提供的一项全面的监控和可观测性服务&#xff0c;使用户能够收集和可视化指标、日志和事件&#xff1b;设置警报&#xff1b;并根据预定义的条件自动执行操作。CloudWatch 提供对 AWS 资源和应用程序的运行状况、性能和运行状态的深入了解&#xff0c;使…

Linux查看jar包错误日志及持久化运行jar包

一、查看jar包运行信息命令&#xff1a;ps -ef | grep java 如图&#xff0c;给出了所部署jar包的环境变量&#xff0c;服务名称&#xff0c;服务端口信息。 这样便能得到部署的jar包是否在服务器成功运行及基本信息。 二、查看日志 启动信息无误&#xff0c;查看日志是否有报错…