6.设计模式

4 min

在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。通俗一点说,设计模式就是给面向对象软件开发中的一些好的设计取个名字。

介绍下工厂模式

直接调用即可返回新对象的函数

  • axios.create 基于传入的配置,创建一个新的请求对象,可以用来设置 base url

介绍下单例模式

单例对象整个系统需要保证只有一个存在

class SingleTon {
  constructor() {}
  // 私有属性,保存唯一实例
  static #instance;

  // 获取单例的方法
  static getInstance() {
    if (SingleTon.#instance === undefined) {
      // 内部可以调用构造函数
      SingleTon.#instance = new SingleTon();
    }
    return SingleTon.#instance;
  }
}
  • 组件库中的 toast,notify 之类的组件,保证单例

介绍下观察者模式

在对象之间定义一个一对多的依赖,当一个对象状态改变时,所有以来的对象会自动收到通知

  • dom 事件绑定
window.addEventListener('load', () => {
  console.log('load 触发 1')
})
window.addEventListener('load', () => {
  console.log('load 触发 2')
})
window.addEventListener('load', () => {
  console.log('load 触发 3')
})
  • vue 中的 watch

介绍下发布订阅模式

类似观察者模式,区别是一个有中间商(发布订阅模式),一个没有中间商(观察者模式)

  • vue2 中的 EventBus

介绍下原型模式

在原型模式下,当我们想要创建一个对象时,会先找到一个对象作为原型,然后通过克隆原型的方式来创建出一个与原型一样(共享一套数据/方法)的对象。在 JavaScript 中,Object.create 就是实现原型模式的内置 api

  • 原型模式:

    • 基于某个对象,创建一个新的对象
    • JS 中,通过 Object.create 就是实现了这个模式的内置 api
    • 比如 vue2 中重写数组方法就是这么做的
  • 创建的方式是通过 Object.create 进行浅拷贝

  • 重写的时候:

    • 调用数组的原方法,获取结果并返回—方法的功能和之前一致
    • 通知了所有的观察者去更新视图
const app = new Vue({
  el: "#app",
  data: {
    arr: [1, 2, 3],
  },
});
app.arr.push === Array.prototype.push; //false

介绍下代理模式

拦截与控制 与目标对象的交互

  • 比如可以通过缓存代理:
    • 缓存获取到的数据
    • 拦截获取数据的请求:
      • 已有缓存:直接返回缓存数据
      • 没有缓存:去服务器获取数据并缓存
  • 提升数据获取效率,降低服务器性能消耗

介绍下迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。简而言之就是:遍历

自定义可迭代对象:

需要符合 2 个协议:

  • 可迭代协议:
    • 给对象增加属方法 Symbol.iterator{}
    • 返回一个符合迭代器协议的对象
  • 迭代器协议
    • 有 next 方法的一个对象,内部根据不同情况返回对应结果:
      • {done:true}, 迭代结束
      • {done:false,value:‘xx’}, 获取解析并接续迭代
const obj = {
  [Symbol.iterator]() {
    const arr = [1, 2, 3, 4, 5];
    let index = 0;
    return {
      next() {
        if (index < arr.length) {
          return { value: arr[index++], done: false };
        } else {
          return { done: true };
        }
      },
    };
    // --- generator function ---
    // function* generator() {
    //   yield 1
    //   yield 2
    //   yield 3
    // }
    // const res = generator()
    // return res
  },
};

for (const element of obj) {
  console.log(element);
}