设计模式

在面向对象语言中,针对特定问题的解决方案(简洁&优雅)

以下模式以js展开。

工厂模式

调用函数,该函数返回一个新对象。
eg1(es5):

function FoodFactory(name,color){
 return {
     name,
     color
  }
}
cosnt food = FoodFactory('土豆','yellow')

eg2(es6+):

class Product {
  constructor(name) {
      this.name = name
  }
  init() {
      console.log('init')
  }
  fun() {
      console.log('fun')
  }
}
let factory = new Factory() // 返回一个实例对象

应用:

  • axios.create()自定义参数配置

单例模式

整个系统中,只有一个该单例对象存在。

class SingleTon {
   static #instance;
   static getInstance(){
       if(!this.#instance){
           this.#instance = new SingleTon();
       }
       return this.#instance
   }
}
const s1 = SingleTon.getInstance();
const s2 = SingleTon.getInstance();
console.log(s1 === s2);  //true

应用:

  • 登录框
  • vuex 和 redux中的store
  • 全局toast

观察者模式

在对象之间定义一个一对多的依赖,当对象状态发生改变时,所有依赖该对象的都会收到通知。(将自身当作发布者)

// 主题 保存状态,状态变化之后触发所有观察者对象
class Subject {
  constructor() {
    this.state = 0
    this.observers = []
  }
  getState() {
    return this.state
  }
  setState(state) {
    this.state = state
    this.notifyAllObservers()
  }
  notifyAllObservers() {
    this.observers.forEach(observer => {
      observer.update()
    })
  }
  attach(observer) {
    this.observers.push(observer)
  }
}

// 观察者
class Observer {
  constructor(name, subject) {
    this.name = name
    this.subject = subject
    this.subject.attach(this)
  }
  update() {
    console.log(`${this.name} update, state: ${this.subject.getState()}`)
  }
}

// 测试
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('02', s)

s.setState(12)

应用:

  • addEventListener(' ', () => {})

发布订阅模式

与观察者模式类似,区别在于观察者模式无中间商,发布订阅存在中间商Event Bus(事件总线)管理注册、订阅、移除事件等。

class Emitter {
    #handlers = { };
    $on(event, callback){
        if(this.#handlers[event] == undefined){
                this.#handlers[event] = [];
        }
        this.#handlers[event].push(callback);
    }

    $emit(event,...args){
      const funcs = this.#handlers[event] || [];
      funcs.forEach(callback => callback(...args));
    }
    $off(event){
          this.#handlers[event] = undefined;
    }
}

const bus = new Emitter();
bus.$on('event1', (...args) => { console.log('111',...args);});
bus.$on('event1', (...args) => { console.log('222',...args);});
bus.$emit('event1','hello','js');
bus.$on('event2', () => { console.log('333');});
bus.$emit('event2');
bus.$off('event2');
bus.$emit('event2');

应用:

  • Vue2 EventBus
  • Vue3 替代方案

原型模式

复制一个已经存在的实例来返回新的实例。

应用:

  • Object.create()
    let obj = {
      name: '111',
      fn1(){
          console.log(this.name);
      }
    }
    const newObj = Object.create(obj);
    newObj.fn1(); // 111
    console.log(newObj == obj); // false 

代理模式

为一个对象提供一个代用品或占位符,以便控制对它的访问。

应用:

  • ES6 的 proxy
  • 缓存代理(如果有缓存走缓存,不需要再发送http请求,减少服务器压力)

迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

自定义对象可迭代,需要要遵循以下要求:

  1. 可迭代协议:增加方法[Symbol.iterator](){},方法返回一个符合迭代器协议的对象。
  2. 迭代器协议:有next方法的对象,方法返回一个对象,包含done(Boolean) 和 value(any) 属性

eg:

const obj = {
   [Symbol.iterator](){
      const arr = ['北京','上海','深圳'];
      let index = 0;
      return {
        next(){
          if(index < arr.length){
            return { done: false, value: arr[index++]};
           }
            return { done: true};
        }
     }
   }
 }
for(const value of obj){
  console.log(value);
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容