当前位置: 首页 > news >正文

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Deep Ocr
  • 828华为云征文|华为云服务器Flexus X搭建悟空crm管理系统——助力企业云上管理(解决APP Referer校验失败问题)
  • Linux中的Vim文本编辑器
  • 设计模式之装饰器模式:让对象功能扩展更优雅的艺术
  • elementUI table 给表头添加气泡显示(鼠标悬浮显示注释)
  • Spring扩展点系列-InstantiationAwareBeanPostProcessor
  • 用ACF和PACF计算出一堆数据的周期个数以及周期时长,数据分析python
  • 【区块链 + 物联网】区块链边缘计算网关设备 | FISCO BCOS应用案例
  • 鸿蒙Next-拉起支付宝的三种方式——教程
  • 2024最新!Facebook手机版和网页版改名教程!
  • 【30天玩转python】条件语句与循环
  • RLC(电阻、电感、电容)
  • 简单的spring batch学习
  • 基础学习之——Docker 的基本概念和优势,以及在应用程序开发中的实际应用。
  • pycharm破解教程
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • 03Go 类型总结
  • ESLint简单操作
  • gf框架之分页模块(五) - 自定义分页
  • HomeBrew常规使用教程
  • js写一个简单的选项卡
  • Mithril.js 入门介绍
  • Redis 中的布隆过滤器
  • underscore源码剖析之整体架构
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 理解在java “”i=i++;”所发生的事情
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 追踪解析 FutureTask 源码
  • ​TypeScript都不会用,也敢说会前端?
  • # 达梦数据库知识点
  • #QT(智能家居界面-界面切换)
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (C#)获取字符编码的类
  • (C语言)共用体union的用法举例
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (十)c52学习之旅-定时器实验
  • (四)Linux Shell编程——输入输出重定向
  • (算法二)滑动窗口
  • (万字长文)Spring的核心知识尽揽其中
  • (五)MySQL的备份及恢复
  • (一)RocketMQ初步认识
  • .DFS.
  • .net 反编译_.net反编译的相关问题
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .net下简单快捷的数值高低位切换
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • [ C++ ] STL_list 使用及其模拟实现
  • [AHK V2]鼠标悬停展开窗口,鼠标离开折叠窗口
  • [C++] 模拟实现list(二)
  • [CareerCup] 12.3 Test Move Method in a Chess Game 测试象棋游戏中的移动方法
  • [FlareOn6]Overlong
  • [Git][分支设计规范]详细讲解