(Observer)被称作发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合。
(Observer)模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
好处:
Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject -- 被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对像将通过一个callback函数得到通知。
ConcreteObserver -- 观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
- /**
- * 发布订阅模式(观察者模式)
- * handles:
- * on: 订阅事件
- * emit: 发布事件
- * off: 删除事件
- **/
- class PubSub {
- constructor() {
- this.handles = {} // 事件处理函数集合
- }
- //订阅事件
- on(eventType, handle) {
- if (!this.handles.hasOwnProperty(eventType)) {
- this.handles[eventType] = []
- }
- if (typeof handle == 'function') {
- this.handles[eventType].push()
- } else {
- throw new Error('缺少回调函数')
- }
- return this;
- }
- // 发布事件
- emit(eventType, ...args) {
- if (this.handles.hasOwnProperty(eventType)) {
- this. Handles[eventType].forEach((item, key, arr) => {
- item.apply(null, args)
- })
- } else {
- throw new Error(`"${eventType}"事件未注册`)
- }
- return this;
- }
- // 删除事件
- off(eventType, handle) {
- if (!this.handles.hasOwnProperty(eventType)) {
- throw new Error(`"${eventType}"事件未注册`)
- } else if (typeof handle != 'function') {
- throw new Error('缺少回调函数')
- } else {
- this.handles[eventType].forEach((item, key, arr) => {
- if (item == handle) {
- this.handles[eventType].splice(key, 1)
- }
- })
- }
- return this;
- }
- }
- let pubsub = new PubSub();
- function callback() {
- console.log('you are so nice')
- }
- // 订阅:如下在事件eventTypeName上添加了两个回调
- pubsub.on('eventTypeName', (...args) => {
- console.log(args.join(' '))
- }).on('eventTypeName', callback)
- // 发布:
- pubsub.emit('eventTypeName', 'whar', 'a', 'fucking day'); //发布 依次执行 eventTypeName 事件中的 所以方法
- pubsub.off('eventTypeName', callback) // 删除只是删除 eventTypeName 事件的 callback 方法
- pubsub.emit('eventTypeName', 'fucking', 'again')
- /*
- 输出值:
- what a fucking day
- you are so nice
- fucking again
- */
总结: 发布—订阅模式的优点非常明显,一为时间上的解耦,二为对象之间的解耦。它的应用非常广泛,既可以 用在异步编程中,也可以帮助我们完成更松耦合的代码编写。发布—订阅模式还可以用来帮助实现一些别 的设计模式,比如中介者模式。从架构上来看,无论是 MVC 还是 MVVM, 都少不了发布—订阅模式的参 与,而且JavaScript本身也是一门基于事件驱动的语言。 当然,发布—订阅模式也不是完全没有缺点(浪费内存)。创建订阅者本身要消耗一定的时间和内存, 而且当你订阅一个消息后,也许此消息最后都未发生,但这个订阅者会始终存在于内存中。另外,发 布—订阅模式虽然可以弱化对象之间的联系,但如果过度使用的话,对象和对象之间的必要联系也将被 深埋在背后,会导致程序难以跟踪维护和理解。特别是有多个发布者和订阅者(b订阅a的消息并发布 给c)嵌套到一起的时候,要跟踪一个bug不是件轻松的事情。