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

2024-09-02 11:12

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

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

这篇关于JS设计模式之“分即是合” - 建造者模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129787

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>