JavaScript的7种设计模式是哪些 为什么要使用设计模式?_今头条

在生活中,很多人都不知道javascript设计模式(JavaScript 的 7 种设计模式) 是什么意思,其实他的意思是非常简单的,下面就是小编搜索到的javascript设计模式(JavaScript 的 7 种设计模式) 相关的一些知识,我们一起来学习下吧!

Javascript设计模式(JavaScript的7种设计模式)

当开始一个新项目时,我们不应该马上开始编程。相反,我们应该首先定义项目的目的和范围,然后列出其功能或规格。如果您已经开始编程或者正在从事一个复杂的项目,那么您应该选择一个最适合您的项目的设计模式。


(资料图片)

什么是设计模式?

在软件工程中,设计模式是软件设计中常见问题的可重用解决方案。设计模式也是有经验的开发人员针对特定问题的更佳实践。可以作为编程的模板。

为什么要使用设计模式?

许多工程师要么认为设计模式浪费时间,要么不知道如何正确使用它们。但是如果你能正确的使用设计模式,它会帮助你写出更好更可读的代码,代码也会更容易维护和理解。

最重要的是,设计模式为软件开发人员提供了一个通用的词汇表。它们可以让学习你的代码的人快速理解代码的意图。例如,如果在您的项目中使用了decorator模式,那么新的开发人员可以很快知道这段代码的功能,这样他们就可以更专注于解决业务问题,而不是试图理解这段代码在做什么。

现在我们知道了什么是设计模式以及它们的重要性,让我们深入了解一下JavaScript中的七种设计模式。

一、模块模式

一个模块是一个独立的代码,所以我们可以在不影响代码其余部分的情况下更新模块。该模块还允许我们通过为变量创建单独的作用域来避免命名空污染。当它们与其他代码解耦时,我们可以在其他项目中重用模块。

模块是任何现代JavaScript应用程序不可或缺的一部分,它有助于保持代码的整洁、独立和有组织。在JavaScript中创建模块的方法有很多种,其中一种就是模块模式。

与其他编程语言不同,JavaScript没有访问修饰符,也就是说,不能将变量声明为私有或公共的。因此,模块模式也可以用来模拟包装的概念。

该模块使用IIFE(立即调用函数表达式)、闭包和函数作用域来模拟封装的概念。例如:

constmyModule=(function(){constprivateVariable="HelloWorld";functionprivateMethod(){console.log(privateVariable);}return{publicMethod:function(){privateMethod();}}})();myModule.publicMethod();

因为是IIFE,所以代码会立即执行,返回的对象会赋给myModule变量。因为闭包,即使在life完成之后,返回的对象仍然可以访问life内部定义的函数和变量。

因此,IIFE内部定义的变量和函数对外部是不可见的,从而使它们成为myModule模块的私有成员。

执行代码后,myModule变量如下所示:

constmyModule={publicMethod:function(){privateMethod();}};

因此,当我们调用publicMethod()时,它会调用privateMethod()例如:

//Prints"HelloWorld"module.publicMethod();

二、揭示模块模式

揭示模块模式是对Christian Heilmann的模块模式的一点改进。模式的问题是我们必须创建新的公共函数来调用私有函数和变量。

在这种模式下,我们将返回对象的属性映射到要公开的私有函数。这就是为什么它被称为揭示模块模式。例如:

constmyRevealingModule=(function(){letprivateVar="Peter";constpublicVar="HelloWorld";functionprivateFunction(){console.log("Name:"+privateVar);}functionpublicSetName(name){privateVar=name;}functionpublicGetName(){privateFunction();}/**revealmethodsandvariable *** yassigningthemtoobjectproperties*/return{setName:publicSetName,greeting:publicVar,getName:publicGetName};})();myRevealingModule.setName("Mark");//printsName:MarkmyRevealingModule.getName();

这种模式让我们更容易知道哪些函数和变量是公共的,这无形中提高了代码的可读性。代码执行后,myRevealingModule如下所示:

constmyRevealingModule={setName:publicSetName,greeting:publicVar,getName:publicGetName};

当我们调用myreealingmodule.setname ("mark ")时,我们实际上调用的是内部publicSetName。当调用myRevealingModule.getName()时,实际调用的是内部publicGetName。例如:

myRevealingModule.setName("Mark");//printsName:MarkmyRevealingModule.getName();

与模块模式相比,模块模式的优势如下:

通过修改return语句中的一行,我们可以将成员从public改为private,反之亦然。

返回的对象不包含任何函数定义,所有的右表达式都是在IIFE中定义的,这样使得代码清晰可读。

三。ES6模块

在ES6之前,JavaScript没有内置模块,所以开发者必须依赖第三方库或模块模式来实现模块。但是从ES6开始,JavaScript有了内置模块。

ES6的模块存储为文件。每个文件只能有一个模块。默认情况下,模块中的所有内容都是私有的。使用export关键字公开函数、变量和类。模块中的代码总是以严格模式运行。

3.1导出模块

有两种方法可以导出函数和变量声明:

在函数和变量声明前添加export关键字。例如:

//utils.jsexportconstgreeting="HelloWorld";exportfunctionsum(num1,num2){console.log("Sum:",num1,num2);returnnum1+num2;}exportfunctionsubtract(num1,num2){console.log("Subtract:",num1,num2);returnnum1-num2;}//ThisisaprivatefunctionfunctionprivateLog(){console.log("PrivateFunction");}

在代码末尾添加export关键字,以公开函数和变量。例如:

//utils.jsfunctionmultiply(num1,num2){console.log("Multiply:",num1,num2);returnnum1*num2;}functiondivide(num1,num2){console.log("Divide:",num1,num2);returnnum1/num2;}//ThisisaprivatefunctionfunctionprivateLog(){console.log("PrivateFunction");}export{multiply,divide};

3.2导入模块

与导出模块类似,有两种方法可以使用import关键字导入模块。例如:

一次导入多个项目。

//main.js//importingmultipleitemsimport{sum,multiply}from"./utils.js";console.log(sum(3,7));console.log(multiply(3,7));

导入所有模块

//main.js//importingallofmoduleimport*asutilsfrom"./utils.js";console.log(utils.sum(3,7));console.log(utils.multiply(3,7));

3.3在导入和导出中使用别名

重命名导出

//utils.jsfunctionsum(num1,num2){console.log("Sum:",num1,num2);returnnum1+num2;}functionmultiply(num1,num2){console.log("Multiply:",num1,num2);returnnum1*num2;}export{sumasadd,multiply};

重命名导入

//main.jsimport{add,multiplya *** ult}from"./utils.js";console.log(add(3,7));console.log(mult(3,7));

四。单一模式

单一对象是只能实例化一次的对象。如果它不存在,singleton模式将创建该类的一个新实例。如果有实例,则只返回对该对象的引用。重复调用构造函数总是会得到相同的对象。

JavaScript是一种内置单例的语言。我们只是不称之为单例,我们称之为对象文字。例如:

constuser={name:"Peter",age:25,job:"Teacher",greet:function(){console.log("Hello!");}};

因为JavaScript中的每个对象都占用一个唯一的内存位置,而当我们调用这个用户对象时,实际上是在返回这个对象的引用。

如果我们试图将用户变量复制到另一个变量并修改它。例如:

constuser1=user;user1.name="Mark";

我们将看到两个对象都被修改了,因为JavaScript中的对象是通过引用而不是通过值来传递的。因此,内存中只有一个对象。例如:

//prints"Mark"console.log(user.name);//prints"Mark"console.log(user1.name);//printstrueconsole.log(user===user1);

您可以使用构造函数来实现单例模式。例如:

letinstance=null;functionUser(){if(instance){returninstance;}instance=this;this.name="Peter";this.age=25;returninstance;}constuser1=newUser();constuser2=newUser();//printstrueconsole.log(user1===user2);

当调用这个构造函数时,它将检查实例对象是否存在。如果对象不存在,则将此变量赋给实例变量。如果对象存在,则只返回对象。

单实例也可以用模块模式实现。例如:

constsingleton=(function(){letinstance;functioninit(){return{name:"Peter",age:24,};}return{getInstance:function(){if(!instance){instance=init();}returninstance;}}})();constinstanceA=singleton.getInstance();constinstanceB=singleton.getInstance();//printstrueconsole.log(instanceA===instanceB);

在上面的代码中,我们通过调用singleton.getInstance方法创建了一个新实例。如果实例已经存在,此方法只返回实例。如果实例不存在,通过调用init()函数创建一个新的实例。

动词 (verb的缩写)工厂模式

工厂模式使用工厂方法创建对象,而不指定特定的类或构造器模式。

模式用于创建对象,而不暴露实例化的逻辑。当我们需要根据具体情况生成不同的对象时,可以使用这种模式。例如:

classCar{constructor(options){this.doors=options.doors||4;this.state=options.state||"brandnew";this.color=options.color||"white";}}classTruck{constructor(options){this.doors=options.doors||4;this.state=options.state||"used";this.color=options.color||"black";}}classVehicleFactory{createVehicle(options){if(options.vehicleType==="car"){returnnewCar(options);}elseif(options.vehicleType==="truck"){returnnewTruck(options);}}}

这里,创建了一个car和一个truck类(带有一些默认值),用于创建新的Car和Truck对象。此外,VehicleFactory类被定义为根据options对象中的Vehiclefactory属性创建并返回一个新对象。

constfactory=newVehicleFactory();constcar=factory.createVehicle({vehicleType:"car",doors:4,color:"silver",state:"BrandNew"});consttruck=factory.createVehicle({vehicleType:"truck",doors:2,color:"white",state:"used"});//PrintsCar{doors:4,state:"BrandNew",color:"silver"}console.log(car);//PrintsTruck{doors:2,state:"used",color:"white"}console.log(truck);

我为类VehicleFactory创建了一个新的工厂对象。然后,我们通过调用factory.createVehicle方法并传递options对象来创建一个新的car或truck对象,其vehicleType属性可能是Car或Truck。

不及物动词装饰模式

装饰模式用于在不修改现有类或构造函数的情况下扩展对象的功能。这种模式可用于向对象添加功能,而无需修改底层代码。

这种模式的一个简单例子是:

functionCar(name){this.name=name;//Defaultvaluesthis.color="White";}//CreatinganewObjecttodecorateconsttesla=newCar("TeslaModel3");//Decoratingtheobjectwithnewfunctionalitytesla.setColor=function(color){this.color=color;}tesla.setPrice=function(price){this.price=price;}tesla.setColor("black");tesla.setPrice(49000);//print *** lackconsole.log(tesla.color);

这种模式的一个更实际的例子是:

假设一辆车的成本取决于它的功能数量。如果没有装饰模式,我们将不得不为不同的功能组合创建不同的类,并且每个类都有一个成本方法来计算成本。例如:

classCar(){}classCarWithAC(){}classCarWithAutoTran *** ission{}classCarWithPowerLocks{}classCarWithACandPowerLocks{}

但是,通过decorator模式,我们可以创建一个基类car,并通过decorator函数为不同的对象添加相应的成本逻辑。

classCar{constructor(){//DefaultCostthis.cost=function(){return20000;}}}//DecoratorfunctionfunctioncarWithAC(car){car.hasAC=true;constprevCost=car.cost();car.cost=function(){returnprevCost+500;}}//DecoratorfunctionfunctioncarWithAutoTran *** ission(car){car.hasAutoTran *** ission=true;constprevCost=car.cost();car.cost=function(){returnprevCost+2000;}}//DecoratorfunctionfunctioncarWithPowerLocks(car){car.hasPowerLocks=true;constprevCost=car.cost();car.cost=function(){returnprevCost+500;}}

首先,我们创建了汽车的基础类Car。然后,为要添加的特性创建一个装饰器,这个装饰器将一个汽车对象作为参数。然后,通过返回更新的汽车成本来覆盖对象的成本函数,并添加一个属性来标识是否添加了一个特性。

要添加新功能,我们只需像下面这样做:

constcar=newCar();console.log(car.cost());carWithAC(car);carWithAutoTran *** ission(car);carWithPowerLocks(car);

最后,我们可以这样计算汽车的成本:

//Calculatingtotalcostofthecarconsole.log(car.cost());

结论

我们已经了解了JavaScript中使用的各种设计模式,但是这里没有可以用JavaScript实现的设计模式。

虽然了解各种设计模式很重要,但不过度使用它们也同样重要。在使用设计模式之前,你应该仔细考虑你的问题是否适合设计模式。要知道某个模式是否适合你的问题,你要研究设计模式及其应用。

\
推荐DIY文章
贵宾犬美容和经典造型:一直在外形上求变,在变化中求经典_全球热推荐
最新超拽霸气说说 希望可以给到大家一些参考 可以了解一下_新消息
天天短讯!fancl卸妆油怎么样 Fancl的主旋律是温和不添加 蕴含三大精华成分
世界热讯:nba2konline过人连招怎么用 来看看常见的十个小技巧吧
【世界热闻】我的梦想绘画作品 今天让我们带着梦想一起纸上旅行
蛮族之王天赋攻略讲解 此英雄的缺点在于极度害怕强控和弱控_今日报
精彩新闻

超前放送