
前端常用的几种设计模式
概念
设计模式是一套被反复使用的代码设计经验的总结,代表了最佳实践。
设计原则
- S - Single Responsibility Principle 单一职责设计模式- 一个程序只做好一件事
- 如果功能过于复杂就拆开,每个部分保持独立
 
- O - OpenClosed Principle 开放/封闭模式- 对扩展开放,对修改封闭
- 增加需求时,扩展新代码,而非修改已有代码
 
- L - LisKov Substitution Principle 里式替换原则- 子类能覆盖父类
- 父类能出现的地方子类就能出现
 
- I - Interface segregation Principle 接口隔离原则- 保持接口的单一独立
- 类似单一原则,这里更关注接口
 
- D - Dependency Inversion Principle 依赖倒转原则- 面向接口编程,依赖于抽象而不依赖于具象
- 使用方只关注接口而不关注具体实现
 
发布-订阅模式(观察者模式)
定义一对一或一对多的依赖关系,当发布者发生变化时,订阅方都会收到通知。
异步编程中可以利用这种模式传递回调函数。比如请求成功或错误等事件。无需关系异步操作运行的内部状态,只需要订阅异步执行完成这个节点。
例子:DOM 节点绑定事件函数,这时 DOM 节点就是发布者,事件函数就是订阅者,
| 1 | const btn=document.getElementById('btn'); | 
| 1 | class Publish { | 
单例模式
确保一个类只有唯一一个实例,并且提供一个访问它的全局访问点。
举例:Window,全局缓存,全局状态管理
单例模式只实例化一次,多次调用实例化函数返回的都是第一次创建的实例对象。
| 1 | //单例模式 | 
实际例子
| 1 | (function () { | 
工厂模式
为了不暴露创建对象的具体逻辑,将逻辑封装在一个函数中,本质上市一个负责生产对象实例的工厂。
根据抽象程度分类:简单工厂,工厂方法,抽象工厂
例子:生产角色
- 简单工厂模式 (适合创建的类比较少的)
| 1 | let UserFactory = function (role) { | 
- 工厂方法 (创建多类对象)
| 1 | let UserFactory = function (role) { | 
- 抽象工厂(创建父类,子类继承父类,具体实现在子类)
| 1 | 
 | 
适配器模式
解决两个接口不兼容的情况。
| 1 | class Plug { | 
例如在项目中拿到的时间是时间戳,我们要展示成日期,就需要一个转换函数。
代理模式
代理是为了控制对象的访问,不让外部对象直接访问到对象。
- 图片懒加载 
- 缓存代理 (缓存请求结果、计算结果) 
| 1 | const multi = function () { | 
- 虚拟代理
 某一个花销很大的操作,可以通过虚拟代理的方式延迟到这种需要它的时候才去创建
 例:使用虚拟代理实现图片懒加载- 创建了一个 Image 对象,并为其绑定了 onload 事件。
- 将 imgNode 先设置为 ‘./loading.gif’ 加载的菊花图。
- 当 Image 对象加载完真实的图片,也就是上文的 ‘./reality.png’ ,将 imgNode 设置为 ‘./reality.png’。
 
| 1 | const imgFunc = ( | 
外观模式
提供一个接口,隐藏内部的逻辑,更加方便外部调用
用于封装 JS 类库,通过封装一些接口用于兼容多浏览器
- 写一个通用的事件侦听器函数
| 1 | const EventUtils = { | 
- 兼容浏览器阻止冒泡、默认事件 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- let N = window.N || {}; 
 N.tools = {
 stopPropagation(e) {
 if (e.stopPropagation) {
 e.stopPropagation();
 } else {
 e.cancelBubble = true;
 }
 },
 preventDefault(e) {
 if (e.preventDefault) {
 e.preventDefault();
 } else {
 e.returnValue = false;
 }
 },
 stopEvent(e) {
 this.stopPropagation(e);
 this.preventDefault(e);
 }
 };
装饰者模式
不需要改变已有的接口,作用是给对象添加功能。
类装饰器,属性装饰器
ES7 的装饰器语法
| 1 | function readonly(target, key, descriptor) { | 
