js设计模式(二)-创建型模式

news2024/11/19 9:37:57

创建型设计模式介绍

在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。

创建型模式由两个主导思想构成。一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合的方式。

创建型模式又分为对象创建型模式和类创建型模式。对象创建型模式处理对象的创建,类创建型模式处理类的创建。详细地说,对象创建型模式把对象创建的一部分推迟到另一个对象中,而类创建型模式将它对象的创建推迟到子类中。

原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

如果使用原型模式,我们只需要调用负责克隆的方法,便能完成同样的功能。> 原型模式的实现关键,是语言本身是否提供了clone方法。ECMAScript 5提供了Object.create方法,可以用来克隆对象。

const Car = function () {this.color = "red";this.brand = "大众";this.mileage = 10000;
};

const car = new Car();

console.log("car:before", car);
// car:before Car { color: 'red', brand: '大众', mileage: 10000 }

car.color = "blue";
car.brand = "BMW";
car.mileage = 999;
car.sayHello = () => console.log("sayHello Func => ", "hello,world!");

console.log("car:after", car);
// car:after Car { color: 'blue', brand: 'BWM', mileage: 999 }
const bentch = Object.create(car);

console.log("bentch:", bentch);
console.log("bentch.color:", bentch.color);
console.log("bentch.brand:", bentch.brand);
console.log("bentch.mileage:", bentch.mileage);
// bentch: Car {}
// bentch.color: blue
// bentch.brand: BWM
// bentch.mileage: 999

bentch.sayHello();
// sayHello Func =>hello,world! 

说实在的,原型模式看了好多人在介绍,并没有一个很清晰的认知。只是认识到了这两点:

1.可以这么理解,所谓原型是依赖于使用场景的,它 使用到了 Object.create 方法去克隆了已经存在的对象,并对原来的数据进行改动的时候不会对原来的数据造成影响。
2.感觉这种方法非常简单,适用于比较简单的场景,能迅速的“实例化”一个新的对象出来。

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1.单例类只能有一个实例。
2.单例类必须自己创建自己的唯一实例。
3.单例类必须给所有其他对象提供这一实例。

class MessageClass {constructor(config) {if (!MessageClass.instance) {const baseConfig = {color: "red",timeOut: 3000,};this.config = Object.assign(baseConfig, config);MessageClass.instance = this;}return MessageClass.instance;}success(msg) {this.config.color = "green";this.msg = msg;this.print("success", msg);}error(msg) {this.config.color = "red";this.msg = msg;this.print("error", msg);}print(type) {console.log(type,"::","color=",this.config.color,"msg=",this.msg,"timeOut=",this.config.timeOut);}
}

const Message = new MessageClass({ timeOut: 5000 });
const Message2 = new MessageClass({ timeOut: 8000 });

Message.success("成功消息!");
Message.error("错误消息!");
Message2.success("成功消息!");
Message2.error("错误消息!");
console.log("Message === Message2 : ", Message === Message2); 

如上所示,我实现了一个 Message 组件,类似 ElementUI 里面的 message 组件的简化版本。

这个无疑是最能诠释单例模式的一个常见的场景了,如打印结果所示,第二次实例化 MessageClass 的时候,入参config并没有生效,这是因为,第一次已经将 intence 创建出来了,以后再也不会走 constroctor 里面的逻辑了,想要修改config,就需要再暴露一个方法去 setConfig 了。

为什么要 Message 要用单例模式呢?因为要保证 每个 Message 不会互相影响,这就要在同一个地址把所有的打印信息放在一起,然后统一去实现动画效果。

其他的使用场景主要是 single-spa 的场景下,例如 vue-router,vuex,dialog,confirm …

工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

class User {constructor(role, pages) {this.role = role;this.pages = pages;}static UserFactory(role) {switch (role) {case "superadmin":return new User(role, ["home", "user-manage", "news-manage"]);break;case "admin":return new User(role, ["home", "news-manage"]);break;case "user":return new User(role, ["home"]);break;default:throw "参数错误!";break;}}
}

const sadmin = User.UserFactory("superadmin");
const admin = User.UserFactory("admin");
const user = User.UserFactory("user");
console.log(sadmin);
console.log(admin);
console.log(user);

const err = User.UserFactory("error"); 

如上所示,是从 B 站视频上的一个例子,用来鉴权所使用的。其实这个逻辑用在这里有点牵强。

但是用来理解套路是够了,就是根据实例化的时候的参数不同,返回不同的对象实例。

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

这个就不粘代码了,工厂模式中可以看到,最终返回的是一个实例后的对象,而抽象工厂模式是使用一个公共的factory方法返回class原型。使用方法也多了一步:

const UserClass = userClassFactory('superadmin')
let user = new UserClass('张三') 

建造者模式(生成器模式)

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

我看了一下相关的介绍,这个模式的使用场景不是很常见,但是有个例子还是很容易理解的:

// 类的链式调用

class CarBuilder {constructor(name) {this.name = name;}buildPart1(params) {this.part1 = params;return this;}buildPart2(params) {this.part2 = params;}
}

const bentch = new CarBuilder("bentch");
bentch.buildPart1({ color: "red" }).buildPart2({ color: "blue" });

console.log(bentch); 

如上所示,如果有一个按顺序实现的比较复杂的需求,例如一个多层循环的tab结构,就需要先实现头部,然后绑定头部事件,按照头部信息触发点击事件切换内容。

同样,链式调用是最直观的方法,其实正常的逻辑会有一个组装方法,把各个模块分开后由 组装方法 build 在一起。

后记

其实,本文的几段代码都是为了演示设计模式而专门杜撰的,说句不好听的,就是为了用而用。

而实际开发中,一般都是多个模式混合着使用,学习这些模式必须学习到其核心原理,而不是要背会这些代码。

简单总结一下:

1.原型模式:基于语言的原生语法,进行新的对象的创建和构建,适用于比较灵活的场景;
2.单例模式:整个页面中涉及到的所有实例,都来自于同一个,适用于来自于同一个模型的多个不同实例,但是需要统一管理所有的实例的场景下;
3.工厂模式:由一个入口,返回多个同类型的实例对象,适用于同属大类但是又有些许区别的的场景;
4.抽象工厂模式:在工厂模式的基础上,同一个入口返回差别比较大的实例对象原型,适用于比较复杂的一对多的创建场景;
5.建造者模式:将整个大业务进行拆解,进行依次组装,适用于流程比较复杂且有前后依赖关系的场景。

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

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

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

相关文章

GCN-LSTM 预测出租车速度 英文 Taxi Speed Prediction Using GCN-LSTM

GCN-LSTM模型预测出租车速度 GCN:又称GNN,图神经网络 LSTM:长短时记忆网络 可做学习参考 Summary One of the most valuable findings in engineering is the determination of taxi speed. Since the GCN-LSTM program software can r…

BOM(一):window对象常见事件、定时器

BOM(一)BOM介绍window 对象的常见事件定时器location 对象navigator 对象history 对象BOM介绍 BOM是浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。 BOM的构成 window 对象的常见事件 1.…

Python|每日一练|斐波那契数列|优化算法|迭代|动态计算|排列组合|时间复杂度:走楼梯

题目名称:走楼梯 时间限制:1000ms内存限制:256M 题目描述 现在有一截楼梯,根据你的腿长,你一次能走 1 级或 2 级楼梯,已知你要走 n 级楼梯才能走到你的目的楼层,请实现一个方法,计…

进程状态|操作系统|什么是pcb|什么是僵尸进程 |什么是孤儿进程 【超详细的图文解释】【Linux OS】

说在前面 今天给大家带来操作系统中进程状态的详解。 本篇博主将通过从进程状态的广泛概念,深入到Linux操作系统详细的一些进程状态。在解释进程状态的过程中,博主还会穿插一些操作系统一些重要概念!本篇干货满满,请大家不要吝啬…

新建的普通用户无法使用sudo的问题

文章目录1.为什么新建用户无法使用sudo指令1. 查看sudoers的权限2. 切换成root用户解决问题1. 切换root用户2.进入 vim编辑器3. 配置成功1.为什么新建用户无法使用sudo指令 [lynVM-8-8-centos ~]$ sudo ls [sudo] password for lyn: lyn is not in the sudoers file. This i…

声学特征提取普及笔记

声学特征如何提取? 一、声学特征预处理 首先进行预处理,就是我们最后要提取一帧一帧的这种声学特征,这个语音信号经过预处理然后提取特征,那么特征也有用原始的傅里叶变换,STFT短时傅里叶变换得到这个语谱图特征,也有用FBANK就没有滤波器的输出,还有用MFCC。预处理包括…

SQL 通配符

通配符可用于替代字符串中的任何其他字符。 SQL 通配符 在 SQL 中,通配符与 SQL LIKE 操作符一起使用。 SQL 通配符用于搜索表中的数据。 在 SQL 中,可使用以下通配符: 通配符描述%替代 0 个或多个字符_替代一个字符[charlist]字符列中的…

Rabbitmq消息队列详解(三)——SpringBoot整合

SpringBoot整合 依赖&#xff1a; <!-- 加入rabbitmq --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>配置&#xff1a; spring:application:nam…

【C初阶】C初阶考试题

选择加编程一、选择题&#xff08;一&#xff09;递归&#xff08;二&#xff09;后置发生死循环&#xff08;三&#xff09;后置运算&#xff08;四&#xff09;操作符运算&#xff08;五&#xff09;全局变量与生命周期&#xff08;六&#xff09;操作符知识&#xff08;七&a…

前端对接微信公众号网页开发流程,前期配置

微信公众号网页开发&#xff0c;其实就是我们开发的h5网页需要放到微信浏览器环境中使用&#xff0c;但是需要对接公众号授权&#xff0c;授权之后可以获取到用户的个人信息&#xff0c;以及可以使用公众号提供的一些API,如&#xff1a;图片上传、图片预览、获取位置信息、微信…

【Java异常】Java异常监控重要手段 --异常链

目录标题前言一、异常链介绍1.1 异常链概述1.2 Java中如何使用异常链二、Throwable1.1 Throwable中哪些API提供存储cause的功能1.2 Throwable中如何获取cause三、项目实战演练示例1:未存储cause示例2:存储cause两层嵌套示例3:存储cause三层嵌套四、总结前言 “异常链”无论是在…

构造题(agc059_b)

https://atcoder.jp/contests/agc059/tasks/ B - Arrange Your Balls Editorial / Time Limit: 2 sec / Memory Limit: 1024 MB Score : 700700 points Problem Statement You have NN balls of colors C_1, C_2, \ldots, C_NC1​,C2​,…,CN​. Here, all colors are rep…

引发C++程序内存错误的常见原因分析与总结

目录 1、概述 2、变量未初始化 2.1、变量未初始化的场景说明 2.2、对0xcccccccc、0xcdcdcdcd和0xfeeefeee等常见异常值的辨识度 3、空指针与野指针 3.1、空指针 3.2、野指针 4、线程栈溢出 5、内存越界 6、内存泄漏 7、堆内存被破坏 8、内存访问违例 8.1、访问64K…

7.Isaac教程--在Python中开发Codelets

在Python中开发Codelets 虽然就性能而言&#xff0c;编写小码的最佳语言是 C&#xff0c;但并非应用程序的所有小码都需要使用相同的语言。 Isaac SDK 还支持 Python codelets&#xff0c;或 pyCodelets&#xff0c;适合那些更熟悉 Python 的人。 本节向您展示如何执行以下操作…

可视化系列讲解:SVG绘制基本图形及如何复用

文章目录一、SVG坐标系二、SVG坐标系单位三、SVG绘制基本图形3.1 矩形3.2 圆形3.3 椭圆3.4 直线3.5 折线3.6 多边型3.7 路径3.8 文字3.9 图片四、SVG元素的组合五、图形元素定义复用和使用定义的复用5.1 defs与use5.2 symbol与use一、SVG坐标系 SVG 使用的坐标系统&#xff08;…

【Python】函数——传递任意数量的实参

传递任意数量的实参和传递任意数量的关键字实参 *args&#xff1a;表示用来接收任意数量的实参&#xff0c;其中&#xff0c;形参*args的星号会让Python创建一个名为args的空元组&#xff0c;并将接收到的任意数量的实参存储在这个元组中。**kwargs&#xff1a;表示用来接收任…

ARX给CAD发送命令的几种方法

本文迁移自本人网易博客&#xff0c;写于2015年11月16日。1、ads_queueexpr( _T("(command\"_POINT\" \"1,1,0\")") );该函数CAD未公开&#xff0c;使用时提前声明下就可以了。可以参考帮助文件中&#xff1a;Tips and Techniques 。2、acDocMan…

嵌入式:人机交互接口设计详解

文章目录键盘和LED的接口原理HD7279A与S3C2410A的连接原理图键盘和LED控制的编程实例LCD显示原理LCD控制器概述嵌入式处理器与LCD的连接S3C2410A的LCD控制器&#xff08;1&#xff09;STN LCD&#xff08;2&#xff09;TFT LCDLCD控制器的框图LCD接口信号STN LCD控制器操作&…

Java IO流 - 转换流的使用详细介绍

文章目录转换流字符输入转换流字符输出转换流转换流 之前我们代码编码和文件编码都是UTF-8, 所以没有出现中文乱码的问题 我们知道代码编码和文件编码的格式如果不一致的话会出现中文乱码的问题 那么如果在开发中, 我们确实会遇到编码不一致的情况如何解决呢? 我们可以使用字符…

【高阶数据结构】手撕红黑树(超详细版本)

&#x1f308;欢迎来到数据结构专栏~~手撕红黑树 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句…