TypeScript 实现观察者模式

1,473 阅读2分钟

这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

观察者模式

最后我们来看看观察者模式,这个模式,在前端其实已经很常用了,我们 DOM 事件监听就是观察者模式,那如果想用一些自定义事件呢?我们也可以自己实现一个观察者模式,来看这个例子。

首先我们创建了一个 EventEmitter 的类,它有一个 listeners 属性用来管理注册过的事件,然后我们仿照 dom 的事件方法,创建了 addEventListener、removeEventListener、emit 方法,分别表示创建,删除,触发事件。

注意这里因为需要支持一个事件被 addEventListener 多次,所以每个 event 对应的,应该是一个回调函数的数组,最后我们在使用它的时候,就可以先创建一个实例,然后再注册事件和触发事件。

type Handler = (data?: any) => void;
class EventEmitter {
  listeners: {
    [eventName: string]: Handler[];
  }
  addEventListener(eventName: string, handler: Handler) {}
  removeEventListener(eventName: string, handler: Handler) {}
  emit(eventName: string, data?: any) {}
}

const eventEmitter = new EventEmitter();

eventEmitter.addEventListener('customClick', () => {
  console.log('custom clicked');
})

eventEmitter.emit('customClick');

习题:理解观察者模式,并计算下面结果

enum PUBLISH_TYPE {
  AGE_SET,
  AGE_GET
};

class Animal {
  private _age: number = 0;
  get age(): number {
    // 广播(发布):有人获取 age 值了
    publishSubscribeStation(PUBLISH_TYPE.AGE_GET, this._age) {
      return this._age;
    }
  }
  set age(_age: number) {
    // 广播(发布):有人设置了 age 值了
    publishSubscribeStation(PUBLISH_TYPE.AGE_SET, _age);
    this._age = _age;
  }
}

// 电视剧(订阅):收到一则广播消息
const publishSubscribeStation = (key: PUBLISH_TYPE, value: any) => {
  switch(key) {
    case PUBLISH_TYPE.AGE_SET: {
      console.log(`set ${value}`);
    };break;
    case PUBLISH_TYPE.AGE_GET: {
      console.log(`get ${value}`);
    };break;
  }
}

const panda = new Animal();
panda.age; // 结果?
panda.age = 10; // 结果?

答案:

get 0

set 10

解析:

观察者模式又叫发布订阅模式,当发布者的状态发生变化时,所有订阅者就会得到通知。

Animalset age 函数和 get age 函数是发布行为的触发者。publishSubscribeStation 函数是发布行为的订阅者。

题目中使用了 getset 关键字,对属性 _age 设置存值函数(setter)和取值函数(getter),每当取 age 属性时,就会调用 get age 函数,然后触犯发布订阅。每当设置 age 属性时,就会调用 set age 函数,然后触犯发布订阅。

题目逻辑本身比较简单,答案为 get 0set 10