配色: 字号:
(最全面的)JavaScript 设计原则指南
2023-09-12 | 阅:  转:  |  分享 
  
?“如果您使用的解决方案不是唯一的解决方案来解决本身就是一个独特挑战的挑战,那么您就利用了 JavaScript设计模式的力量”。软件语言已
经存在了几十年。至此,软件语言的生命周期已经被很好地理解了。在任何语言的生命周期中,许多此类可重用解决方案都是由给定语言社区中的大
量开发人员制作和测试的。通过复合开发人员经验的力量,创建了称为设计模式的解决方案,并使之对大众有用。这些解决方案支持创建优化方法,
以基于更少的设计模式来解决大量问题类型。“设计模式是软件设计中常见问题的可重用解决方案”我们从设计模式中获得什么好处?行之有效的解
决方案:许多软件开发人员都使用设计模式。被许多开发人员成功使用,我们在实现给定的设计模式时获得了更大的成功确定性。当设计模式成为主
流时,您可以放心地知道它们已经被多次修改和重构。经过验证的解决方案通常是最优的,考虑到边缘情况,并且可用于各种用例。易于重用:当解
决方案可重用时,可以对其进行修改以解决多个特定问题。设计模式记录了一个可重用的解决方案,该解决方案与任何特定问题无关,而是与设计模
式帮助克服的一系列挑战相关。富有表现力:很多时候,设计模式可以以简明扼要的方式解释大型解决方案。降低重构代码的需求:大多数设计模式
都会考虑代码依赖性、现有和未来的依赖性。例如,开放封闭设计原则 - 无需重构已编写的代码。相反,您创建一个新类(用其他非 js 语
言实现接口)并添加代码。您可以限制使用设计模式重构代码的需要。简化沟通:由熟悉设计模式的软件工程师组成的团队能够通过其代码库语言更
轻松地进行内部沟通。他们还能够与外部沟通潜在的解决方案、值得注意的未来问题以及所有架构设计。设计模式简化了沟通。精简代码库站点:由
于其优雅、高效且经过深思熟虑的方法,设计模式通常需要更少的代码,最终只需一个团队的代码库。“在深入研究之前,让我们简要回顾一下 J
avaScript 的历史,以更好地理解许多现代设计模式的构建背景。”JavaScript 历史(简短)课程在 Web 开发领域,
JavaScript 是当今最流行的编程语言之一。一开始,JavaScript 并没有打算成为这种令人印象深刻的世界范围内接受的语
言,具有反应式前端、模块化代码存储库以及可通过 npm 安装的数百万个包。甚至还不太接近,一开始 JavaScript 更像是“粘
合剂”,允许您将 HTML 元素的各种显示粘在一起。最初被称为客户端脚本语言,世界上第一个网络浏览器之一 - Netscape N
avigator,利用 JavaScript 显示静态 HTML。当然,这导致了我们现在所说的浏览器之战。浏览器是新的、热门的、爆
炸式的——它们是科技行业的下一个重大事件。Mozilla(以前称为 Netscape Communications)、Micros
oft Explorer 以及最终的 Chrome 等大玩家都在争夺浏览器的荣耀。作为这场浏览器战争中每个浏览器背后的驱动力,大公
司们正在研究、开发和创建新的和改进的方法来实现自己的客户端脚本语言。Netscape:?JavaScript(实际上,Brenda
n Eich 创建了最初的 JS)微软:?JScript(有人知道那是什么吗?)作为那个时代的开发人员,我想象到了巨大的挫败感。这
些实现有很大不同。开发并不针对所有浏览器,而是针对个别浏览器。正如我所想象的那样,愤怒的软件工程师拿着干草叉和火把聚集在一起,其数
量可与我们世界历史上最恶意的战争的军队相媲美。随着愤怒的开发人员的崛起,我们只有一个需求 - 为所有浏览器选择一种 MO
FU 语言。(在我的想象中,我们的开发者祖先在这个时代更像是伟大的维京战士,渴望战争,并在争取简化和荣耀的战斗中面临死亡
。我最近也在 Hulu 上观看维京人 - 这可能让我的想象力猖獗。 .)于是,ECMAScript诞生了。你问的 ECMAScri
pt 是什么?自由、包容性和非疯狂标准化的呼声。ECMAScript 是所有现代浏览器都试图支持的标准化脚本语言规范。如果您想进行
传统的人类语言类比,它确实有许多更像不同方言的实现。我喜欢将 ECMAScript 视为所有脚本语言和 JavaScript 的始
祖,因为它是英雄的儿子 - 英雄中的英雄,战胜一切困难的斗士,因为它太棒了而赢得了所有女士的青睐(但说实话,JavaScript
是各位工程师最常用的软件语言之一)JavaScript 是源自 ECMAScript 的最流行的方言。由于 ECMAScript
进入了现实世界,它为软件工程社区做了一些重要的事情。它标准化了维基百科上列出的许多重要内容。浏览器对 ECMAScript 版本
6 (ES6) 及更高版本的支持仍然不完整,必须转换为 ES5 才能得到完全支持。什么是 JavaScript(除了 Awesom
e)?让我们介绍一些非常重要的 JavaScript 语言特性。在深入研究本文中讨论的 JS 设计模式之前,您需要对 JavaSc
ript 的这些属性有一些了解和背景。读这篇文章,这里有一个问题要问你...“什么是 JavaScript?”一种可能的答案可能是
:“JavaScript 是一种轻量级、解释性、面向对象的编程语言,具有一流的功能,最常被称为网页脚本语言。”嗯……呵呵?!基本上
,这个非常复杂的引用是由一个或多个比我聪明得多的人写的,意思是这样的:JS 内存占用低JS很容易实现JS简单易学JS 的语法与其他
流行语言(例如 C++ 和 Java)类似JS是一种脚本语言这意味着它的代码是解释而不是编译的JS有程序支持JS具有面向对象的支持
JS 具有函数式编程风格支持JS 对于开发者来说很灵活!(直到S坏了,然后才痛)这些是 JavaScript 的属性或特征,
您可以在许多其他流行的软件语言中找到它们 - 但是,正如我们许多人都清楚的那样,JavaScript 很时髦并且有自己的节奏。Ja
vaScript 支持一流函数一等函数非常强大,但一开始也有些难以掌握。据说一种编程语言具有一流函数只是意味着该语言中的函数被像任
何其他变量一样对待。第一类函数可以:作为参数传递给其他函数/ We pass a function as the argumen
t /function action (name, payload, callback_function) {?let cont
ext = { name, payload };?callback_function(context);};action(''log
-alert'', ''hello world'', function (context) { console.log( "The ac
tion context: ", context, "The action name: ", context.name, "T
he action payload: ", context.payload );})第一类函数可以是:由另一个函数返回functi
on sayHello() { return function() {?console.log("Hello!"); }}第一类函
数可以:作为值分配给变量const foo = function() { console.log("foobar");}// In
voke it using the variablefoo();基于 JavaScript 原型JavaScript 是面向对象的
——因此它支持对象。现在,大多数不熟悉 JavaScript 的人会从逻辑上考虑对象,然后是类,甚至可能是继承。JavaScrip
t 有一些不同的方法......JavaScript 的普通形式不支持类...相反,JavaScript 使用所谓的基于原型或基于
实例的?继承ES6中,正式引入了Class这个术语。在撰写本文时,所有浏览器都完全支持 ES6,因此我们可以使用Class关键字
- 但它在像 JS 这样的原型语言中的工作方式仍然不同。基于原型的编程面向对象编程风格行为重用(称为继承)是通过作为原型的委托重用
现有对象的过程来执行的我们将在本文的设计模式部分进一步深入探讨。理解原型对于 JS 来说非常重要,但我们暂时不要添加太多细节。Ja
vaScript 事件循环您听说过回调函数吗?如果您习惯在 JavaScript 世界中工作,我相信您已经习惯了。回调函数是作为参
数发送到另一个函数的函数(由于函数是一等公民,因此可以接受)。作为参数传递的函数将在事件触发后调用。通常,这用于订阅事件。?编辑示
例:鼠标右键单击事件触发要调用的函数 - 因此是回调函数事件有一个附加的侦听器。每次该事件触发时(否则该事件将丢失)消息被发送到消
息队列该消息队列(FIFO - 先进先出)同步处理。这个过程就是我们所知的 JavaScript事件循环。每个队列消息具有关联功能
一旦队列消息出队运行时在处理任何其他消息之前完全执行该函数。如果一个函数包含其他函数调用它们都是在处理队列中的新消息之前执行的。这
称为运行到完成while (queue.waitForMessage()) {?queue.processNextMessage(
);}队列.waitForMessage()同步等待新消息。加工完成后从队列中处理一条新消息(如果有的话)每条正在处理的消息都有自
己的堆栈并进行处理,直到堆栈为空。您是 Clean Code Studio 内容的粉丝吗?“加入时事通讯以获取更多此类内容!”您是
否听说过 JavaScript 中使用的“非阻塞”或异步术语?当执行异步操作时它不会停止或停止运行时该程序能够处理其他事情例如:接
收用户输入在等待异步操作完成时异步操作对于主执行线程来说是非阻塞的。这是一项非常有用的功能,既可以在 JavaScript 内部使
用,也可以在外部用于特定的 JavaScript 用例。异步与同步是 JavaScript 中的一个巨大主题,但如果我们也深入研究
,我们永远不会了解我们的设计模式 - 这是本文讨论的主题。什么是设计模式设计模式是软件设计中常见问题的可重用解决方案。我们来看看设
计模式的一些类别原型模式创建设计模式,你是如何做到的?您是否注意到任何经常重复出现的问题?您是否已经克服了为解决此问题而专门设计的
解决方案?假设您的这个解决方案没有得到全球认可和记录。每次出现或遇到此问题时,您都会使用此解决方案。您创建的这个解决方案是可重用的
,整个开发人员社区将是这种模式的受益者。这不会立即使其成为一种设计模式。程序员可能拥有良好的代码,但只是将一些看起来像模式的东西误
认为是实际的设计模式——而归根结底——它不是真正的设计模式。是什么使某些东西成为实际的设计模式?答:开发者普遍共识。如果您能够从大
量开发人员那里获得意见,那么您就走在正确的道路上。通过了解创建模式本身的过程,并让自己熟悉现有模式,您就开始学习该过程。任何设计模
式都必须经历这个阶段才能成为成熟的模式。这称为原型模式。如果原型模式满足一定时期的测试所定义的标准,并且必须由不同数量的开发人员进
行测试,那么它就是未来的模式。它必须在许多挑战的背景下进行测试,在许多场景中进行分析,并最终通过许多测试和普遍的社区共识被证明是一
种有用且可重用的设计模式。为了展示如何使给定软件语言的开发人员社区认可成熟的模式,我们已经完成了大量的工作和文档。反模式同样值得注
意的是,与软件中的许多事物一样,给定概念的倒置也是如此。设计模式的反面是什么?反模式反模式代表了一种不良实践。反模式的一个例子是修
改Object类原型。在 JavaScript 中,一切几乎都继承自Object.?JavaScript 使用基于原型的继承,因此
在任何情况下你现在都已经改变了一些东西。您已经创建了一个变体,可以改变 JavaScript 中的所有其他设计模式、概念或技术。这
是不好的,因此是一种反设计模式。设计模式分类设计模式的分类有多种方式,但这里有一个流行的分类。创意设计模式结构设计模式行为设计模式
并发设计模式架构设计模式创意设计模式创建设计模式是用于创建对象的模式。这些是优化创建单个或一组对象的机制的设计模式。建造者设计模式
工厂设计模式单例设计模式原型设计模式抽象工厂设计模式都是创意设计模式的例子结构设计模式结构设计模式与对象关系相关。这些类型的设计模
式确保如果系统的一部分发生变化,整个系统不需要随之改变。代理设计模式桥梁设计模式立面设计模式适配器设计模式装饰设计模式享元设计模式
复合设计模式都是结构设计模式的例子。行为设计模式行为设计模式识别、实现和改进系统中对比对象之间的通信。它们用于支持给定软件系统的对
比部分具有同步数据。状态设计模式访客设计模式命令设计模式纪念品设计模式迭代器设计模式中介者设计模式观察者设计模式策略设计模式责任链
设计模式都是行为设计??模式的例子。并发设计模式并发设计模式用于实现多线程编程范例的解决方案。调度程序设计模式主动对象设计模式核反
应设计模式都是并发设计模式的例子架构设计模式架构设计模式用于实现架构最佳实践。MVP 设计模式(模型-视图-演示者)MVC设计模式
(模型-视图-控制器)MVVM 设计模式(模型-视图-视图模型)都是架构设计模式的例子。设计模式示例每一种设计模式都代表特定类型
问题的特定类型解决方案。最好的设计模式从来都不是通用的。为了成为最好的软件工程师,我们需要学习何时应该使用给定的设计模式。我们需要
从上下文的角度了解哪种设计模式是最好的。对于给定的问题使用不正确的设计模式不仅没有帮助,而且可能会损害我们和我们的应用程序目标。构
造函数模式在经典的面向对象软件语言中,构造函数是我们首先了解的特殊函数之一。这是我们用来用一组默认属性值初始化对象的函数。我们如何
在 JavaScript 中创建对象,最常见的方法有哪些?let obj = {}let obj = Object.create(
Object.prototype)let obj = new Object();创建对象后,有四种方法(自 ES3 起)可以实际向
新创建的 js 对象添加属性。点符号obj.key = ''value''括号表示法obj[''key''] = ''value''Objec
t.definePropeties 表示法Object.defineProperties(obj, { ''keyOne'': { v
alue: ''one'', writable: true }, ''keyTwo'': { value: ''two'', writable
: false },})大括号表示法是在 JavaScript 中创建对象的最流行的方法。点符号或方括号是定义属性和设置这些属性值
的最流行的方法。正如我们前面谈到的,JS 实际上并不支持传统的面向对象类。new然而,我们在 JavaScript 中确实有关键字
。我们可以通过new关键字支持 javascript 中的构造函数。我们可以使用函数作为构造函数,最终使用属性初始化对象,并使用
为该对象传入初始属性值new。function Person(name, email, admin) { this.name =
name this.email = email this.admin = admin this.isAdmin = () => t
his.admin === true this.isNotAdmin = () => this.admin === false}l
et tim = new Person(''Tim'', ''tim@gmail.com'', false)let sarah = new
Person(''Sarah'', ''sarah@gmail.com'', true)tim.isAdmin() // falseti
m.isNotAdmin() // truesarah.isAdmin() // truesarah.isNotAdmin() /
/ false我们可以改进这个语法吗?我们真的想在对象的构造函数中定义函数吗?我们还可以利用对象prototype来向对象添加方法
。看看这个语法。function Person(name, email, admin) { this.name = name th
is.email = email this.admin = admin}Person.prototype.isAdmin = fu
nction () { return this.admin === true}Person.prototype.isNotAdmi
n = function () { return this.admin === false}let tim = new Perso
n(''Tim'', ''tim@gmail.com'', false)let sarah = new Person(''Sarah'', ''
sarah@gmail.com'', true)tim.isAdmin() // falsetim.isNotAdmin() //
truesarah.isAdmin() // truesarah.isNotAdmin() // false模块设计模式当 Jav
aScript 能够实现一些奇特的事情时,它总是让人惊叹不已。是的,有时这些特性令人困惑——然而,这也伴随着实现一些非常强大的模式
的能力。与其他语言相比,JavaScript 的奇怪之处之一是它支持访问修饰符的能力。在我们深入研究模块模式之前,让我们首先深入研
究 JavaScript 中的闭包。理解闭包对于真正理解 JavaScript 中一些最强大的模式至关重要。JavaScript
闭包闭包是一个可以访问父作用域的函数,即使在父函数关闭之后也是如此。闭包帮助我们通过作用域来模仿访问修饰符的行为。我们通过一个例子
来学习一下。let Countable = (function () { let count = 0 return functio
n () {?return count++ }})()console.log(Countable()) // 1console.l
og(Countable()) // 2console.log(Countable()) // 3在此示例中,我们使用IIFE?-
又名立即调用函数表达式。每次我们调用 countable 时,它??所绑定的函数都会立即执行。我们能够做到这一点要归功于 JS
中函数作为一等公民的力量。当这个函数被调用时,我们实际上返回另一个嵌套函数。由于我们无法count从 Countable 外部访问
该变量 - 我们通过设计模式的力量,使其成为privateCountable 对象的成员。count是私人的。通过闭包的力量,我们
能够创建具有私有和公共部分的对象。这些称为模块,每当我们需要隐藏对象的某些子部分的行为时,这些模块就非常有用。我们能够修改哪些行为
是公开的,哪些部分是私有的而不是公开的。这是另一个例子:const Collection = (function() { // i
tems is a private property let items = []; // everything returned
engulfed public properties and methods return {?add: function (i
tem) { items.push(item)?},?remove: function (item) { let index =
items.indexOf(item) if (index >= 0) items.splice(index, 1)?},?all
: function () {?return JSON.parse(JSON.stringify(items))?} }})()C
ollection.add(''Tim'')Collection.add(''Sarah'')Collection.add(''Raphae
l'')console.log(Collection.all()) // [''Tim'', ''Sarah'', ''Raphael'']Co
llection.remove(''Sarah'')console.log(Collection.all()) // [''Tim'',
''Raphael'']这种模式允许我们在对象的私有部分和公共部分之间引入清晰的分区。对于具有经典面向对象背景经验的开发人员来说,这个
概念很熟悉。话虽如此,这并不能让一切都像我们希望的那样完美。如果您想更改成员的可见性怎么办?您需要更改代码,在使用该成员的所有地方
修改它,因为我们需要设置奇怪或不同的设置才能实现模块设计模式将私有部分更改为公共部分(反之亦然)需要您更改代码中的多个内部依赖点。
揭示模块设计模式让我们改进上面说明的模块设计模式。我们的主要区别在于,我们将在模块的私有范围内编写整个对象逻辑,然后通过返回匿名对
象来公开我们想要公开的部分。当将私有成员映射到相应的公共成员时,我们还可以更改私有成员的命名。const Collection =
(function () { / Private Members / let items = [] function all
() { ?return JSON.parse(JSON.stringify(items)) } function add (
item) { ?items.push(item) } function remove (item) { let index =
items.indexOf(item) if (index >= 0) items.splice(index, 1) } /
Public Members / return {?addItem: add,?allItems: all,?removeIte
m: remove, }})()Collection.addItem(''Tim'')Collection.addItem(''Sam''
)Collection.addItem(''Ben'')console.log(Collection.allItems()) // [
''Tim'', ''Sam'', ''Ben'']Collection.remove(''Sam'')console.log(Collectio
n.allItems()) // [''Tim'', ''Ben'']上面直接显示的这个示例就是所谓的揭示模块模式。这是我们能够实现模块模
式的至少 3 种不同方式之一。揭示模块模式与模块设计模式的所有其他变体之间有什么区别?差异主要取决于公共成员的引用方式。结果,揭示
模块设计模式更容易使用和修改。话虽如此,这种设计模式在某些情况下可能很脆弱(请记住,没有一种设计模式是普遍适用的)。当询问您是否应
该使用揭示模块模式时,需要考虑以下几个有问题的情况。私有函数是指公共函数。在这种情况下,我们无法使用此设计模式覆盖公共函数。当我们
尝试覆盖它时,由于私有函数继续引用该函数的私有实现,我们将给我们的软件引入一个错误。如果我们有一个指向私有变量的公共成员,然后继续
尝试从模块外部覆盖公共成员,则我们不应该使用此设计模式。在这种情况下,其他函数仍然会引用变量的私有值,从而在我们的软件中引入错误。
单例设计模式单例设计模式用于我们只需要一个类的一个实例的情况。Singleton 设计模式属于创建设计模式类别。想象一下,例如,我
们需要一个对象,其中包含在运行时甚至开始之前定义的应用程序的一些配置设置。在这些场景中,没有必要每次需要此配置对象时都创建一个全新
的对象。用户定义的配置设置需要一次性加载到一个对象中,以便我们的 JS 运行时可以访问配置设置,但我们不需要每次尝试访问配置设置时
都重新创建该对象。const Singleton = (function () { // Private config let
config; function initializedConfigurationSettings (values) { this
.random = Mathod.random() values = values || {} this.number = val
ues.number || 5 this.size = values.size || 10 } ?return { getConf
ig: function (values) { // we initialize the singleton value only
once if (config === undefined) { config = new initializedConfigu
rationSettings(values) } return config }?}}();const Configuration
Settings = singleton.getConfig({ app: ''HelloWorld'', environment:
''local'' })console.log(ConfigurationSettings) // { app: ''HelloWorl
d'', environment: ''local'' }ConfigurationSettings.getConfig({ "numb
er": 8 })// same randomDecimalValue as in the first config - aka
we''ve proven it''s the same object在此示例中,您可以看到我们生成了一个随机数。如果您要使用此代码
- 第一次调用后,随机生成的数字将是相同的singleton.getConfig。这是我们证明单例对象每次返回相同对象的方法。我们
只创建该对象一次,然后每次都返回相同的配置对象。观察者设计模式在我看来,观察者设计模式是最强大的设计模式之一——尤其是在 Java
Script 中。观察者设计模式是一种行为设计模式。我们可以通过这种设计模式来改善软件应用程序的对比部分之间的通信。这种设计模式在
实现时确实有多种变体,但其最基本的形式有两个主要部分。第一部分:主题第二部分:观察员主题负责处理与某个主题相关的所有操作。观察家订
阅了这个主题。观察者可以订阅和取消订阅主题。想象一下我们有两种类型的对象:一个客户。一家商店。客户对特定品牌的产品(例如:iPho
ne)感兴趣,该产品很快就会在商店中上架。让客户每天访问商店并检查产品可用性是资源密集型的。相反,客户可以订阅商店提供的 iPho
ne 主题。解决方案:具有某种有趣状态的客体就是主体。由于它还将通知其他对象有关其状态的更改,我们也将其称为发布者。所有其他对象(
在我们的例子中为客户)都将成为订阅者。let publisher = {}(function (container) { // r
epresents a unique subscription id to a topic let id = 0 contain
er.subscribe = function (topic, callback) {?if (!(topic in contai
ner)) container[topic] = []?container[topic].push({ id: id++, cal
lback: callback })?return id } container.unsubscribe = function (
topic, id) { let subscribers = [] for (let subscriber of containe
r[topic]) ?if (subscriber.id !== id) subscribers.push(subscriber
) container[topic] = subscribers } container.publish = function (
topic, data) {?for (let subscriber of container[topic]) ?subscrib
er.callback(data) }})(publisher)let subscription_1 = publisher.su
bscribe(''mouseClicked'', function (data) {?console.log(?"Sam''s cal
lback for mouse click: ", ?"Event Data: ",?JSON.stringify(data)?)
})let subscription_2 = publisher.subscribe(''mouseHovered'', functi
on (data) { ?console.log(?"Sam''s callback for mouse hovered: ", ?
"Event Data: ",?JSON.stringify(data)?) })let subscription_3 = pub
lisher.subscribe(''mouseClicked'', function (data) {?console.log( "
Sarah''s callback function for mouse click: ", "Event Data: ", JS
ON.stringify(data)?)})publisher.publish(''mouseClicked'', { data: ''
data1'' })publisher.publish(''mouseHovered'', { data: ''data2'' })// u
nsubsribe from an event publisher.unsubcribe(''mouseClicked'', subs
cription_3)publisher.publish(''mouseClicked'', { data: ''data1'' })pu
blisher.publish(''mouseHovered'', { data: ''data2'' })当我们需要基于正在触发的单个事
件执行多个操作时,观察者设计模式非常有用。例子:想象一个场景,我们需要对 API 进行多个 AJAX 调用,然后我们需要更进一步,
根据初始调用集返回的数据结果执行其他 AJAX 调用。您必须将 AJAX 调用嵌套在另一个调用中,这可能会进入一种称为回调地狱的情
况。使用发布者/订阅者模式是一种更优雅的解决方案。观察者设计模式的缺点对我们系统的各个部分进行困难的测试。原型设计模式正如本文全文
所述,JS 不支持经典 OOP 本机理解中的类。因此,对象之间的继承是使用基于原型的编程来实现的。这使我们能够创建可以充当Java
Script 中创建的其他对象的原型的对象。原型对象用作构造函数创建的每个对象的蓝图。让我们在 JS 中展示这个原型模式实现的简单
实现。let PersonPrototype = { hi: function () { console.log(`Hello,
my name is ${this.name}, and I''m ${this.age}.`) }, bye: function
() { console.log(`I''m ${this.name} and I''m saying bye now!`) }}fu
nction Person (name, age) {?age = age || 26?name = name || "John
Doe"?function constructorFunction(name, age) {?this.age = age?thi
s.name = name?}?constructorFunction.prototype = PersonPrototype?l
et obj = new constructorFunction(name, age)?return obj}let person
1 = Person()let person2 = Person("Tim", 38)person1.hi() // "hello
, my name is John Doe and I''m 26person2.hi() // "hello, my name i
s Tim and I''m 38原型是继承在 JS 中的工作方式,这只是其实现的一个简单示例。命令设计模式当我们想要将执行命令的对
象与发出我们想要执行的命令的对象分离时,我们可以使用命令设计模式。例子:想象一下这样一种情况:我们的应用程序对给定的应用程序服务使
用大量 API 调用。这些 API 服务发生变化。理解为这个问题实现可靠的编码解决方案的挑战中的这种奇怪现象,我们可以使用命令设计
模式。我们想要实现一个抽象层。该抽象层将调用 API 服务的对象与告诉它们何时调用 API 服务的对象分开。此实现将避免需要在需要
调用服务的所有位置修改代码。相反,我们必须更改本身进行调用的对象 - 这就是说我们只需要在一处而不是多个地方进行更改。谈到设计模式
时,一个重要的要点是,我们必须习惯于理解在决定使用任何给定设计模式时所做的权衡。我们是否添加了不需要的抽象层,或者我们是否正在解决需要抽象层正确解决的依赖侵蚀问题?let invoker = { add: function (x, y) { return x + y }, subtract: (x, y) { return x - y },}let manager = { execute: function (name, args) {?if (name in invoker) { ?return invoker[name].apply(invoker, [].slice.call(arguments, 1))?}?return false }}console.log(manager.execute("add", 3, 5)) // 8console.log(manager.execute("subtract", 5, 3)) // 2立面设计模式什么是门面设计模式?使用这种设计模式,我们能够在公开显示的内容和幕后实现的内容之间创建一个抽象层。这种设计模式对于提高可读性非常有用。这种模式的一个很好的例子是来自 DOM 操作库(例如 jQuery、Dojo 或 D3)的选择器。您可能已经注意到使用这些库时它们具有非常强大的选择器功能;您可以编写复杂的查询,例如:jQuery(".parent .child div.span")在这个例子中,选择特征语法被简化了很多。尽管表面上看起来很简单,但所实现的场景背后的逻辑要复杂得多。在幕后,我们做了很多工作,但面向外部的 API 最终用户(在本例中开发人员是最终用户)被简化了。我们喜欢简化:)下一步设计模式是软件工程师工具带中最强大的工具之一 - 如果您希望将自己变成一名高级 JavaScript 开发人员,那么您应该了解大量的设计模式。知道如何、何时、何地实现设计模式以及权衡,这些都是领导团队的 JavaScript 工程师应该非常了解的特征。在理解这些设计模式时,重构大师是一个很好的资源。我们可以在本文中展示一百多个设计原则示例,但事实是一篇文章无法涵盖所有??可用的设计原则。我强烈建议将每周学习两个新的设计原理作为目标。一年后,您将掌握 104 条设计原则。作为软件工程师,您对任何团队和组织的价值都会增加数倍。设计模式:可重用的面向对象软件的元素。?
献花(0)
+1
(本文系云端筑梦师A...原创)