一、工厂模式
一种创建对象的设计模式,将对象的创建和使用分开
使用场景: UI组件库—不同类型的按钮,dialog等,我想用一个primary的按钮,button厂创建并返回,我只负责使用
二、单例模式
保证一个类只有一个实例,并提供一个全局访问点来访问该实例
前端用的较多
使用场景:状态管理—在不同组件之间共享和管理状态数据
浏览器中的window、document 都算是单例
优点: 减少内存开销
实现方式:
- 挂载到全局,global,window,会污染全局,不推荐
- 闭包
三、发布订阅模式
也叫-消息队列模式。一对多的依赖关系,其中一个对象状态变化其它依赖项都会收到通知并更新
使用场景:可以实现组件之间的通信-eventbus,vuex,redux中的store
优点:解耦,可扩展性,灵活
缺点:没有及时取消订阅可能引起内存泄露
引申:Vue的响应式原理?
vue2:0bject.defineProperty()劫持对象属性的getter和setter方法,利用发布订阅的设计模式,数据的读操作都会触发getter函数,写操作都会触发setter函数。
缺点:无法通过下标方式修改数组数据,
底层原因:不是不能实现,是性能问题,性能代价和获得用户体验收益不成正比
vue3:通过Proxy对对象进行代理,从而实现数据劫持,可以完美监听任何数据变化
缺点:Proxy是ES6语法,有兼容性问题
四、观察者模式
概念与发布订阅类似
区别:
观察者模式:主体直接管理观察者列表,有变化直接通知更新
发布订阅:维护一个中间的消息队列,实现了解耦
五、装饰器模式
Angular,Nest.js用的较多
用于对象功能的扩展,动态的添加新的行为和功能
通俗理解:手机壳就是手机的装饰器
例如给方法加上debounce来限制规定时间内只调用一次,debouce其实就是一个包装函数
Angular中的常用装饰器:
类装饰器:@Component,@Injectable
属性装饰器:@input,@0utput
六、迭代器模式
可迭代对象:实现Symbol.iterator方法的对象,即它的原型链上肯定有一个键为[Symbol.iterator]的属性内置,迭代器一定实现了next()方法
object不可迭代
可迭代对象有:String、Array、TypedArray、Map、Set
生成器函数Generator也是可迭代的
引申
for…in:数组,对象都可以遍历,拿到的是数组的index,或者对象的key
for…of:迭代器,不能遍历对象,支持数组,Map,Set等
for比forEach效率高:for直接用索引迭代数组或对象元素,foreach需要用回调
七、原型模式
- 什么是原型链?
原型链是一种机制。它允许我们在对象上定义属性和方法,让我们可以从原型链上继承属性和方法
当我们访问一个属性或者方法时,会先从自身寻找,找不到就去它的原型链上找,找不到就会从原型的原型上找,直至到原型链终端。终端也没有,最终会返回null
- 什么是原型模式?
一种利用原型链的设计模式。使用0bject.create()来创建对象,支持修改原型链的属性和方法来支持新对象的属性行为。
优点:减少创建对象的事件成本,利用现有对象作为基础,通过克隆clone创建新对象,从而提高了性能和效率。
八、职责链模式
webserver常用,如koa2
为了避免请求发送者和多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的方式连成一条链,请求沿着链传递,知道有一个对象能处理它。
九、计算属性模式
使用0bject.defineProperty()来实现计算属性模式,通过get和set方法来计算属性值
例如:vue中的computed
computed和watch的区别?
computed:
1.支持缓存,只有依赖的数据发生变化了才会重新计算
2.不支持异步
watch:
1.不支持缓存,数据发生变化就会触发相应操作
2.支持异步
3.immediate:组件加载立即触发回调函数
4.deep:深度监听
使用场景:当需要进行数值计算并依赖其它数据时使用computed,当需要进行异步或者开销较大的操作时,使用watch
十、路由模式
通常用于SPA应用的导航和状态管理路由模式,通过解析ur1路径来确认显示哪个页面,并使用历史记录API来管理页面状态
常见框架有:Vue Router,React Router,Angular Router