# 发布订阅模式

发布订阅模式,包含发布者,订阅者,事件调度中心3个角色.发布者和订阅者是松散耦合的,它们互不关心对方是否存在,它们关注的是事件本身 发布者通过事件调度中心提供的emit方法发布事件,订阅者则通过on方法订阅事件

  class EventEmitter {
    constructor() {
      this.listeners = {};
    }
    /**
     * @description:监听事件
     * @param {*} type 事件类型
     * @param {*} cb 触发函数
     * @return {*}
     */
    on(type, cb) {
      if (!this.listeners[type]) {
        this.listeners[type] = [];
      }
      this.listeners[type].push(cb);
    }
    /**
     * @description: 发布事件
     * @param {*} type 事件类型
     * @param {array} args 触发函数参数
     * @return {*}
     */
    emit(type, ...args) {
      if (this.listeners[type]) {
        this.listeners[type].forEach((cb) => {
          cb(...args);
        });
      }
    }
    /**
     * @description: 移除某个事件的一个监听者
     * @param {*} type
     * @param {*} cb
     * @return {*}
     */
    off(type, cb) {
      if (this.listeners[type]) {
        let index = this.listeners[type].findIndex((item) => item === cb);
        if (index !== -1) {
          this.listeners[type].splice(index, 1);
        }
        if (this.listeners[type].length === 0) {
          delete this.listeners[type];
        }
      }
    }
    /**
     * @description: 移除某个事件所有监听者
     * @param {*} type
     * @return {*}
     */
    offAll(type) {
      if (this.listeners[type]) {
        delete this.listeners[type];
      }
    }
  }

  /**
   * @description: 发布-订阅模式
   * @param {*}
   * @return {*}
   */
  class PubSub {
    constructor() {
      this.events = {};
    }
    /**
     * @description: 订阅
     * @param {*} type 事件类型
     * @param {*} cb 回调函数
     * @return {*}
     */
    subscribe(type, cb) {
      if (!this.events[type]) {
        this.events[type] = [];
      }
      this.events[type].push(cb);
    }
    /**
     * @description: 发布
     * @param {*} type
     * @param {array} args
     * @return {*}
     */
    publish(type, ...args) {
      if (this.events[type]) {
        this.events[type].forEach((cb) => {
          cb(...args);
        });
      }
    }
    /**
     * @description: 移除某个事件的一个订阅行为
     * @param {*} type
     * @param {*} cb
     * @return {*}
     */
    unsubscribe(type, cb) {
      if (this.events[type]) {
        let index = this.events[type].findIndex((item) => item === cb);
        if (index !== -1) {
          this.events[type].splice(index, 1);
        }
        if (this.events[type].length === 0) {
          delete this.events[type];
        }
      }
    }
    /**
     * @description: 移除某个事件的所有订阅行为
     * @param {*} type
     * @return {*}
     */
    unsubscribeAll(type) {
      if (this.events[type]) {
        delete this.events[type];
      }
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

vue的EventEmitter就是一个典型的订阅发布模式,发布者通过调度中心的emit方法发布事件,订阅者则通过on方法订阅事件

  class EventEmitter {
    constructor() {
      this.listeners = {};
    }
    /**
     * @description:监听事件
     * @param {*} type 事件类型
     * @param {*} cb 触发函数
     * @return {*}
     */
    on(type, cb) {
      if (!this.listeners[type]) {
        this.listeners[type] = [];
      }
      this.listeners[type].push(cb);
    }
    /**
     * @description: 发布事件
     * @param {*} type 事件类型
     * @param {array} args 触发函数参数
     * @return {*}
     */
    emit(type, ...args) {
      if (this.listeners[type]) {
        this.listeners[type].forEach((cb) => {
          cb(...args);
        });
      }
    }
    /**
     * @description: 移除某个事件的一个监听者
     * @param {*} type
     * @param {*} cb
     * @return {*}
     */
    off(type, cb) {
      if (this.listeners[type]) {
        let index = this.listeners[type].findIndex((item) => item === cb);
        if (index !== -1) {
          this.listeners[type].splice(index, 1);
        }
        if (this.listeners[type].length === 0) {
          delete this.listeners[type];
        }
      }
    }
    /**
     * @description: 移除某个事件所有监听者
     * @param {*} type
     * @return {*}
     */
    offAll(type) {
      if (this.listeners[type]) {
        delete this.listeners[type];
      }
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# 观察者模式

观察者模式与发布订阅模式相比,耦合度更高,通常用来实现一些响应式的效果。在观察者模式中,只有两个主体,分别是目标对象Subject,观察者Observer。

  • 观察者需Observer要实现update方法,供目标对象调用。update方法中可以执行自定义的业务代码。
  • 目标对象Subject也通常被叫做被观察者或主题,它的职能很单一,可以理解为,它只管理一种事件。Subject需要维护自身的观察者数组observerList,当自身发生变化时,通过调用自身的notify方法,依次通知每一个观察者执行update方法。
 //观察者
  class Observer {
    constructor(cb) {
      if (typeof cb !== 'function') {
        throw new Error('Observer构造器必须传入函数类型!');
      } else {
        this.cb = cb;
      }
    }
    update() {
      this.cb();
    }
  }
  //目标对象
  class Subject {
    constructor() {
      // 维护观察者列表
      this.observerList = [];
    }
    addObserver(observer) {
      this.observerList.push(observer);
    }
    notify() {
      this.observerList.forEach((observer) => {
        observer.update();
      });
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28