JS 设计模式
为什么会出现设计模式
随着公司业务的不断迭代和扩张,项目的复杂程度也在不断加强,如果不采取一些方法那么项目会变的难以开发及维护;而设计模式就是为了解决这样的问题诞生的。
设计模式通过将变与不变分离,确保变化的部分灵活、不变的部分稳定,来帮助开发者开发出“健壮”的代码,保证代码的可扩展性和高维护性。
JavaScript 设计模式的原则
JavaScript 设计模式围绕“单一功能”和“开放封闭”这两个原则来展开
下面我们来介绍下js的几种设计模式吧
一、构造器模式
对于构造器模式大家非常熟悉,我们平时使用的构造函数就是应用了构造器模式
构造函数每new一个实例,就会开启一个内存空间,像name、age的属性值是不一样的,所以给他们独自的内存空间是正确的,但是toStr是个方法,每个实例的方法都一样的,却也开辟了自己的内存空间,这样造成了内存的浪费
二、原型模式
要理解原型模式,我们必须要理解什么是原型对象
只要创建了一个新函数(非箭头函数),该函数就会有一个prototype属性,这个属性指向函数的原型对象,在默认情况下,所有的原型对象都会有一个constructor(构造函数)属性,而这个属性是一个指向prototype属性所在的函数的指针。
如果使用原型模式,我们只需要调用负责克隆的方法,便能完成同样的功能。还以Person为例
但是呢这样new实例都指向了Person.prototype对象,指向了同一内存空间,虽然解决了toStr这个方法在构造器模式的内存浪费问题,Person的实例对象其他的属性相互受到了影响。
所以我们让构造器模式与原型模式结合一下
或者用ce6的新语法class
三、工厂模式
工厂模式是一种创建型模式,也可以说,工厂模式就是创建对象的一种方式。
应用:工厂模式被广泛应用于软件工程领域,来抽象的创建特定对象的过程。
作用:创建对象;降低代码冗余度。
应用场景:要批量生产同种类的对象;如,你要生成一个班级没个学生某次考试的分数,有语文、数学、英语等。这时候你创建一个“工厂”,把信息丢到工厂里,工厂就给你造一个学生的考分出来,非常方便。
使用工厂模式创建对象
只要我们往工厂函数里面塞参数,工厂函数就会像生产产品一样造个学生的分数出来;但是工厂模式的本质是将创建对象的过程进行了封装,我们创建一个 学生分数(stuScore) 时无法知道其具体的数据类型,只知道是个对象,可大多的实际开发中我们有需要知道这个对象到底是个StuScore的实例还是Student的实例。
四、抽象工厂模式
定义:使用一种工厂模式就可以创建多个抽象角色。
抽象工厂模式向用户提供了一个基础接口,使用户在不指定产品的具体的情况下,创建出多个用户产品族中的产品对象。
抽象工厂像极了生产工厂,抽象工厂是实现子类继承父类的方法。
例如:
抽象工厂不可以接创建实例,个人认为在项目中应该蛮实用的 少了很多的new 组合比较灵活
五、建造者模式
把一个复杂对象的分离层和表示层分离,同样的构建过程可以采用不同的表示
建造者模式是一步一步的创建对象,他允许用户只通过指定复杂的对象的类型和内容就可以都见他们,用户不需要制定内部的具体构造细节
应用场景
当一个构造函数的参数较多时使用,根据参数进行分类然后分别构建各个部分,最后挂在对象的属性上
建造者模式关注的是过程和细节
如下面代码
其实异步照样可行
六、单例模式/单体模式
保证一个类仅又一个实例,并提供一个访问它的全局访问点
单例模式主要解决的问题就是节约资源,保持访问一致性。
我们常见的单一有 window、 redux中的store等等
可能有的人就会说了, 根据let不允许重复的特性,直接用 let 定义的一个对象不就是一个单例嘛;这么说也没错,但是有弊端。如容易命名冲突、容易被覆盖等等
当然,单例也不能乱用,只有符合 唯一 和 全局访问 的对象才能用
看下单例是怎么实现的
优点:
- 单例模式创建后在内存中只存在一个实例,节约了内存开支和实例化时的性能开支,特别是需要重复使用一个创建开销比较大的类时,比起实例不断地销毁和重新实例化,单例能节约更多资源,比如数据库连接;
- 单例模式解决了对资源的多重占用,如写文件操作时,因为只有一个实例,可以避免对一个文件进行同时操作;
- 只使用一个实例,减小了垃圾回收机制 GC(Garbage Collecation)的压力,在浏览器中大的表现就是系统卡顿减少、操作更流畅、CPU 资源占用更少;
缺点:
- 单例模式对扩展不友好,不容易扩展,因为单例模式是自行实例化的,没有接口。
- 与单一职责原则冲突,一个类应该只关心内部逻辑,不关心外面怎样来实例化。
更新中。。。