关于设计模式:观察者模式与发布订阅模式区别-JS

5次阅读

共计 2425 个字符,预计需要花费 7 分钟才能阅读完成。

观察者模式

当对象之间存在一对多的依赖关系时,当被察看的对象状态产生扭转时,所有察看它的对象都会收到告诉,这就是观察者模式。

根本思维

在观察者模式中,只有两种主体:指标对象 (Subject) 和 观察者 (Observer)。
在观察者模式中,Subject 对象领有增加、删除和告诉一系列 Observer 的办法等,而 Observer 对象领有 update 更新办法等。在 Subject 对象增加了一系列 Observer 对象之后,Subject 对象则维持着这一系列 Observer 对象,当无关状态产生变更时 Subject 对象则会告诉这一系列 Observer 对象进行更新。

长处

  • 耦合度高,通常用来实现一些响应式的成果;
  • 角色很明确,没有事件调度核心作为两头者,指标对象 Subject 和观察者 Observer 都要实现约定的成员办法;
  • 单方分割严密,指标对象的主动性很强,本人收集和保护观察者,并在状态变动时被动告诉观察者更新;

实现

// 指标对象
class Subject {constructor() {this.observers = []
  }

  add (observer) {this.observers.push(observer)
  }

  notify() {
    this.observers.map(observer => {if (observer && typeof observer.update === 'function') {observer.update()
      }
    })
  }

  remove(observer) {const idx = this.observers.findIndex(itm => itm === observer)
    if (idx !== -1) {this.observers.splice(idx, 1)
    }
  }
}

// 观察者
class Observer {constructor(name) {this.name = name}

  update() {console.log(`${this.name} updated`)
  }
}

const subject = new Subject()
const o1 = new Observer('Nina')
const o2 = new Observer('Jack')

subject.add(o1)
subject.add(o2)

console.log('第一次告诉:')
subject.notify()

subject.remove(o1)

console.log('删除 Nina 后,再次告诉:')
subject.notify()

输入为:

公布 - 订阅模式

基于一个事件(主题)通道,心愿接管告诉的对象 Subscriber 通过自定义事件订阅主题,被激活事件的对象 Publisher 通过公布主题事件的形式告诉各个订阅该主题的 Subscriber 对象,这就是公布订阅模式。
公布订阅模式中有三个角色:发布者 Publisher,事件调度核心 Event Channel,订阅者 Subscriber

特点

  • 公布订阅模式中,对于发布者 Publisher 和订阅者 Subscriber 没有非凡的束缚,他们借助事件调度核心提供的接口公布和订阅事件,互不理解对方是谁;
  • 涣散耦合,灵便度高,罕用作事件总线;
  • 易了解,可类比于 DOM 事件中的 dispatchEventaddEventListener

毛病

  • 当事件类型越来越多时,难以保护,须要思考事件命名的标准,也要防备数据流凌乱。

实现

class EventEmitter {constructor() {this.list = {}
    if (!EventEmitter.instance) {EventEmitter.instance = this}
    return EventEmitter.instance
  }

  on(name, fn) {if (!this.list[name]) {this.list[name] = []}
    this.list[name].push(fn)
  }

  emit(...rest) {const name = ([].shift.call(rest))
    const fns = this.list[name] || []
    fns.forEach((fn) => {fn.apply(this, rest)
    })
  }

  off(name) {this.list[name] = []}

  clean() {this.list = {}
  }
}

const e1 = new EventEmitter()
e1.on('go', (name) => console.log(`${name} 走了 `))
e1.on('come', (name) => console.log(`${name} 来了 `))

e1.emit('go', 'Nina')
e1.emit('go', 'Jack')
e1.emit('come', 'Bill')

二者区别

  • 概念与实现上

    • 从概念上了解,两者没什么不同,都在解决对象之间解耦,通过事件的形式在某个工夫点进行触发,监听这个事件的订阅者能够进行相应的操作。
    • 在实现上有所不同,观察者模式对订阅事件的订阅者通过发布者本身来保护,后续的一些列操作都要通过发布者实现。公布订阅模式是订阅者和发布者两头会有一个事件总线,操作都要通过事件总线实现。
  • 耦合

    • 观察者模式是面向指标和观察者编程的,用于耦合指标和观察者。观察者和被观察者之间还存在耦合,被观察者还是晓得观察者的;
    • 公布 – 订阅模式是面向调度核心编程的,用于解耦发布者和订阅者。发布者和订阅者不须要晓得对方的存在,通过 音讯代理 进行通信,解耦更加彻底;
  • 关系

    • 观察者模式的观察者和被观察者就像 商家 - 顾客 的关系,当商品有更新等,商家会间接告诉订阅的顾客。
    • 公布订阅模式的发布者和订阅者,就像 商家 -APP- 顾客 的关系,顾客(订阅者)在 APP 上订阅商品告诉,待商品有更新时,商家(发布者)通过 APP 告诉订阅的顾客(订阅者)。
  • 从应用层面上讲

    • 观察者模式,多用于单个利用外部;
    • 公布订阅模式,更多的是一种跨利用的模式(cross-application pattern),比方消息中间件;
正文完
 0