百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

前端开发需要了解常用7种JavaScript设计模式

sinye56 2024-10-22 16:25 9 浏览 0 评论


作者 | Deven

译者 | 王强

策划 | 小智

转发链接:https://mp.weixin.qq.com/s/Lw4D7bfUSw_kPoJMD6W8gg

前言

JavaScript 中的设计模式指的是一些可重用的解决方案,这些方案适用于编写 JavaScript Web 应用程序时常见的一些问题。

本文最初发布于 codesource.io 网站,经原作者授权由 InfoQ 中文站翻译并分享。

开发人员将 JavaScript 设计模式作为解决问题的模板是很合适的,但并不是说这些模式可以代替开发人员的工作。

通过设计模式,我们可以将许多开发人员的经验结合起来,以优化过的方式来构造代码,从而解决我们所面对的问题。设计模式还提供了用于描述问题解决方案的通用词汇表,而不是去枯燥地描述代码的语法和语义。

JavaScript 设计模式可帮助开发人员编写出井井有条、美观且结构合理的代码。尽管设计模式很容易重用,但它们并不是要取代开发人员的工作;它们是开发人员的支持与辅助,提供了与特定应用程序无关的通用解决方案,从而尽量避免那些可能导致 Web 应用程序的开发工作出现重大问题的小漏洞。

与临时方案相比,它们消除了不必要的重复,从而缩减了代码库的整体大小,并让我们的代码更加健壮。

在本文中,我将探讨 7 中最出色和最受欢迎的 JavaScript 设计模式,这些模式主要归为以下三类:创作设计模式、结构设计模式和行为设计模式。

1、构造函数设计模式

这是一种特殊的方法,用于在分配内存后初始化新创建的对象。由于 JavaScript 一般来说是面向对象的,所以它打交道最多的就是对象。于是我打算深入研究对象构造函数。在 JavaScript 中创建新对象有三种方法可用。

以下创建构造函数设计模式的一种方法。

// 创建一个新的空对象
var newObject = {};
// 创建一个新的空对象
var newObject = Object.create(Object.prototype);
var newObject = newObject();

要访问函数的属性,你需要初始化对象。

const object = new ConstructorObject();

上面的 new 关键字告诉 JavaScript,一个 constructorObject 应该充当一个构造函数。这个设计模式并不支持继承。更多细节可以参考这里:

https://addyosmani.com/resources/essentialjsdesignpatterns/book/#constructorpatternjavascript

2、原型模式

原型模式是基于原型继承的。在这种模式中,被创建的对象充当其他对象的原型。实际上,原型(prototype)是被创建的每个对象构造函数的蓝图。

示例

var myCar= {
name:"Ford Escort",
brake:function(){
console.log("Stop! I am applying brakes");
}
Panic : function (){
console.log ( "wait. how do you stop thuis thing?")
}
}
// 使用 object create 实个新的例化一 car
var yourCar= object.create(myCar);
// 现在它就是另一个的原型了
console.log (yourCar.name);]

3、模块设计模式

模块(module)设计模式对原型模式做了一些改进。模块模式设置了不同类型的修饰符(私有和公共)。你可以创建相似的函数或属性而不会发生冲突。我们还可以灵活地公开重命名函数。这个设计模式的一个缺陷是无法覆盖(override)外部环境中创建的函数。

示例

function AnimalContainter () {
const container = [];
function addAnimal (name) {
container.push(name);
}
function getAllAnimals() {
return container;
}
function removeAnimal(name) {
const index = container.indexOf(name);
if(index < 1) {
throw new Error('Animal not found in container');
}
container.splice(index, 1)
}
return {
add: addAnimal,
get: getAllAnimals,
remove: removeAnimal
}
}
const container = AnimalContainter();
container.add('Hen');
container.add('Goat');
container.add('Sheep');
console.log(container.get()) //Array(3) ["Hen", "Goat", "Sheep"]
container.remove('Sheep')
console.log(container.get()); //Array(2) ["Hen", "Goat"]

4、单例模式

在仅需要创建一个实例的情况下(例如一个数据库连接),这个模式是必需的。在这个模式中,只能在关闭连接时创建一个实例,或者在打开新实例之前必须关闭已有的实例。此模式也称为严格模式,它的一个缺点是测试时的体验很差,因为它隐藏的依赖项对象很难挑出来进行测试。

示例

function DatabaseConnection () {
let databaseInstance = null;
// 追踪特定时间创建实例的数量
let count = 0;
function init() {
console.log(`Opening database #${count + 1}`);
// 现在执行操作
}
function createIntance() {
if(databaseInstance == null) {
databaseInstance = init();
}
return databaseInstance;
}
function closeIntance() {
console.log('closing database');
databaseInstance = null;
}
return {
open: createIntance,
close: closeIntance
}
}
const database = DatabseConnection();
database.open(); //Open database #1
database.open(); //Open database #1
database.open(); //Open database #1
database.close(); //close database

5、工厂模式

这个模式的创新之处在于,它不需要构造函数就能创建对象。它提供了用于创建对象的通用接口,我们可以在其中指定要创建的工厂(factory)对象的类型。这样一来,我们只需指定对象,然后工厂会实例化并返回这个对象供我们使用。当对象组件设置起来很复杂,并且我们希望根据所处的环境轻松地创建不同的对象实例时,使用工厂模式就是很明智的选择。在处理许多共享相同属性的小型对象,以及创建一些需要解耦的对象时也可以使用工厂模式。

示例

// Dealer A
DealerA = {};
DealerA.title = function title() {
return "Dealer A";
};
DealerA.pay = function pay(amount) {
console.log(
`set up configuration using username: ${this.username} and password: ${
this.password
}`
);
return `Payment for service ${amount} is successful using ${this.title()}`;
};
//Dealer B
DealerB = {};
DealerB.title = function title() {
return "Dealer B";
};
DealerB.pay = function pay(amount) {
console.log(
`set up configuration using username: ${this.username}
and password: ${this.password}`
);
return `Payment for service ${amount} is successful using ${this.title()}`;
};
//@param {*} DealerOption
//@param {*} config
function DealerFactory(DealerOption, config = {}) {
const dealer = Object.create(dealerOption);
Object.assign(dealer, config);
return dealer;
}
const dealerFactory = DealerFactory(DealerA, {
username: "user",
password: "pass"
});
console.log(dealerFactory.title());
console.log(dealerFactory.pay(12));
const dealerFactory2 = DealerFactory(DealerB, {
username: "user2",
password: "pass2"
});
console.log(dealerFactory2.title());
console.log(dealerFactory2.pay(50));

6、观察者模式

观察者(observer)设计模式在许多对象同时与其他对象集通信的场景中用起来很方便。在观察者模式中不会在状态之间发生不必要的事件 push 和 pull;相比之下,所涉及的模块仅会修改数据的当前状态。

示例

function Observer() {
this.observerContainer = [];
}
Observer.prototype.subscribe = function (element) {
this.observerContainer.push(element);
}
// 下面是从 container 中移除一个元素
Observer.prototype.unsubscribe = function (element) {
const elementIndex = this.observerContainer.indexOf(element);
if (elementIndex > -1) {
this.observerContainer.splice(elementIndex, 1);
}
}
/**
* we notify elements added to the container by calling
* each subscribed components added to our container
*/
Observer.prototype.notifyAll = function (element) {
this.observerContainer.forEach(function (observerElement) {
observerElement(element);
});
}

7、命令模式

最后介绍的是命令(command)模式。命令设计模式将方法调用、操作或请求封装到单个对象中,以便我们可以自行传递方法调用。命令设计模式让我们可以从任何正在执行的命令中发出命令,并将责任委托给与之前不同的对象。这些命令以 run() 和 execute() 格式显示。

(function(){
var carManager = {
// 请求的信息
requestInfo: function( model, id ){
return "The information for " + model + " with ID " + id + " is foo bar";
},
// 现在购买这个 car
buyVehicle: function( model, id ){
return "You have successfully purchased Item " + id + ", a " + model;
},
// 现在 arrange viewing
arrangeViewing: function( model, id ){
return "You have successfully booked a viewing of " + model + " ( " + id + " ) ";
}
};
})();

小结

对于 JavaScript 开发人员来说,使用设计模式的好处很多。设计模式的一些主要优点包括提升项目的可维护性,还能减少开发周期中不必要的工作。JavaScript 设计模式可以为复杂的问题提供解决方案,提升开发速度并提高生产率。但并不能说这些设计模式就可以让开发人员偷懒了。

推荐JavaScript经典实例学习资料文章

浅谈浏览器架构、单线程js、事件循环、消息队列、宏任务和微任务

了不起的 Webpack HMR 学习指南(上)「含源码讲解」

了不起的 Webpack HMR 学习指南(下)「含源码讲解」

10个打开了我新世界大门的 WebAPI(上)「实践」

10个打开了我新世界大门的 WebAPI(中)「实践」

10个打开了我新世界大门的 WebAPI(下)「实践」

「图文」ESLint 在中大型团队的应用实践

Deno是代码的浏览器,你认同吗?

前端存储除了 localStorage 还有啥?

Javascript 多线程编程?的前世今生

微前端方案 qiankun(实践及总结)

「图文」V8 垃圾回收原来这么简单?

Webpack 5模块联邦引发微前端的革命?

基于 Web 端的人脸识别身份验证「实践」

「前端进阶」高性能渲染十万条数据(时间分片)

「前端进阶」高性能渲染十万条数据(虚拟列表)

图解 Promise 实现原理(一):基础实现

图解 Promise 实现原理(二):Promise 链式调用

图解 Promise 实现原理(三):Promise 原型方法实现

图解 Promise 实现原理(四):Promise 静态方法实现

实践教你从零构建前端 Lint 工作流「干货」

高性能多级多选级联组件开发「JS篇」

深入浅出讲解Node.js CLI 工具最佳实战

延迟加载图像以提高Web网站性能的五种方法「实践」

比较 JavaScript 对象的四种方式「实践」

使用Service Worker让你的 Web 应用如虎添翼(上)「干货」

使用Service Worker让你的 Web 应用如虎添翼(中)「干货」

使用Service Worker让你的 Web 应用如虎添翼(下)「干货」

前端如何一次性处理10万条数据「进阶篇」

推荐三款正则可视化工具「JS篇」

如何让用户选择是否离开当前页面?「JS篇」

JavaScript开发人员更喜欢Deno的五大原因

仅用18行JavaScript实现一个倒数计时器

图文细说JavaScript 的运行机制

一个轻量级 JavaScript 全文搜索库,轻松实现站内离线搜索

推荐Web程序员常用的15个源代码编辑器

10个实用的JS技巧「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」

深入JavaScript教你内存泄漏如何防范

手把手教你7个有趣的JavaScript 项目-上「附源码」

手把手教你7个有趣的JavaScript 项目-下「附源码」

JavaScript 使用 mediaDevices API 访问摄像头自拍

手把手教你前端代码如何做错误上报「JS篇」

一文让你彻底搞懂移动前端和Web 前端区别在哪里

63个JavaScript 正则大礼包「值得收藏」

提高你的 JavaScript 技能10 个问答题

JavaScript图表库的5个首选

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

可视化的 JS:动态图演示 - 事件循环 Event Loop的过程

教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」

可视化的 js:动态图演示 Promises & Async/Await 的过程

原生JS封装拖动验证滑块你会吗?「实践」

如何实现高性能的在线 PDF 预览

细说使用字体库加密数据-仿58同城

Node.js要完了吗?

Pug 3.0.0正式发布,不再支持 Node.js 6/8

纯JS手写轮播图(代码逻辑清晰,通俗易懂)

JavaScript 20 年 中文版之创立标准

值得收藏的前端常用60余种工具方法「JS篇」

箭头函数和常规函数之间的 5 个区别

通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events

「前端篇」不再为正则烦恼

「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能

深入细品浏览器原理「流程图」

JavaScript 已进入第三个时代,未来将何去何从?

前端上传前预览文件 image、text、json、video、audio「实践」

深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系

推荐13个有用的JavaScript数组技巧「值得收藏」

前端必备基础知识:window.location 详解

不要再依赖CommonJS了

犀牛书作者:最该忘记的JavaScript特性

36个工作中常用的JavaScript函数片段「值得收藏」

Node + H5 实现大文件分片上传、断点续传

一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」

【实践总结】关于小程序挣脱枷锁实现批量上传

手把手教你前端的各种文件上传攻略和大文件断点续传

字节跳动面试官:请你实现一个大文件上传和断点续传

谈谈前端关于文件上传下载那些事【实践】

手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件

最全的 JavaScript 模块化方案和工具

「前端进阶」JS中的内存管理

JavaScript正则深入以及10个非常有意思的正则实战

前端面试者经常忽视的一道JavaScript 面试题

一行JS代码实现一个简单的模板字符串替换「实践」

JS代码是如何被压缩的「前端高级进阶」

前端开发规范:命名规范、html规范、css规范、js规范

【规范篇】前端团队代码规范最佳实践

100个原生JavaScript代码片段知识点详细汇总【实践】

关于前端174道 JavaScript知识点汇总(一)

关于前端174道 JavaScript知识点汇总(二)

关于前端174道 JavaScript知识点汇总(三)

几个非常有意思的javascript知识点总结【实践】

都2020年了,你还不会JavaScript 装饰器?

JavaScript实现图片合成下载

70个JavaScript知识点详细总结(上)【实践】

70个JavaScript知识点详细总结(下)【实践】

开源了一个 JavaScript 版敏感词过滤库

送你 43 道 JavaScript 面试题

3个很棒的小众JavaScript库,你值得拥有

手把手教你深入巩固JavaScript知识体系【思维导图】

推荐7个很棒的JavaScript产品步骤引导库

Echa哥教你彻底弄懂 JavaScript 执行机制

一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧

深入解析高频项目中运用到的知识点汇总【JS篇】

JavaScript 工具函数大全【新】

从JavaScript中看设计模式(总结)

身份证号码的正则表达式及验证详解(JavaScript,Regex)

浏览器中实现JavaScript计时器的4种创新方式

Three.js 动效方案

手把手教你常用的59个JS类方法

127个常用的JS代码片段,每段代码花30秒就能看懂-【上】

深入浅出讲解 js 深拷贝 vs 浅拷贝

手把手教你JS开发H5游戏【消灭星星】

深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】

手把手教你全方位解读JS中this真正含义【实践】

书到用时方恨少,一大波JS开发工具函数来了

干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)

手把手教你JS 异步编程六种方案【实践】

让你减少加班的15条高效JS技巧知识点汇总【实践】

手把手教你JS开发H5游戏【黄金矿工】

手把手教你JS实现监控浏览器上下左右滚动

JS 经典实例知识点整理汇总【实践】

2.6万字JS干货分享,带你领略前端魅力【基础篇】

2.6万字JS干货分享,带你领略前端魅力【实践篇】

简单几步让你的 JS 写得更漂亮

恭喜你获得治疗JS this的详细药方

谈谈前端关于文件上传下载那些事【实践】

面试中教你绕过关于 JavaScript 作用域的 5 个坑

Jquery插件(常用的插件库)

【JS】如何防止重复发送ajax请求

JavaScript+Canvas实现自定义画板

Continuation 在 JS 中的应用「前端篇」

作者 | Deven

译者 | 王强

策划 | 小智

转发链接:https://mp.weixin.qq.com/s/Lw4D7bfUSw_kPoJMD6W8gg

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: