定义
观察者模式 在软件设计中是一个对象,维护一个依赖列表,当任何状态发生改变自动通知它们。
demo
举例
假设你正在找一份软件工程师的工作,对“香蕉公司”很感兴趣。所以你联系了他们的HR,给了他你的联系电话。他保证如果有任何职位空缺都会通知你。这里还有几个候选人也你一样很感兴趣。所以职位空缺大家都会知道,如果你回应了他们的通知,他们就会联系你面试。
代码
发布者
//发布者class Subject{constructor(){this.obseverse = []}add(observe){this.obseverse.push(observe)}notify(data){this.obseverse.forEach( observe=> observe.update(data))}}
观察者
// 观察者class Observer {update(data) {console.log(data);}}
为发布者添加观察者
let subject = new Subject();let ob = new Observer();//目标添加观察者了subject.add(ob);//目标发布消息调用观察者的更新方法了subject.notify(); //update
subject通知观察者就像一个发布者通知他的订阅者。这也就是很多书和文章使用“发布-订阅”概念来解释观察者设计模式
延伸-发布订阅模式
定义
在发布-订阅模式,消息的发送方,叫做发布者(publishers),消息不会直接发送给特定的接收者,叫做订阅者。
意思就是发布者和订阅者不知道对方的存在。需要一个第三方组件,叫做信息中介
代码
class Event {constructor () {// 储存事件的数据结构// 为查找迅速, 使用对象(字典)this._cache = {}}// 订阅on(type, callback) {// 为了按类查找方便和节省空间// 将同一类型事件放到一个数组中// 这里的数组是队列, 遵循先进先出,// 即新绑定的事件先触发if(this._cache[type]){// 如果该消息存在let fns = this._cache[type];if(!fns.includes(callback)){fns.push(callback)}}else {this._cache[type] = [callback]}return this}// 发布trigger(type, data) {let fns = this._cache[type];if(Array.isArray(fns)) {fns.forEach((fn) => {fn(data)})}return this}// 解绑off (type, callback) {let fns = this._cache[type];if(Array.isArray(fns)) {if(callback) {let index = fns.indexOf(callback);if(index !== -1) {fns.splice(index, 1)}} else {// 全部清空fns.length = 0}}return this}}// 创建了一个发布中心var observer = new Event();// 某某某订阅了go事件observer.on('go',function () {console.log(111);});observer.on('go',function (option) {console.log(222);console.log(option.url);});// go事件执行了并通知了他的订阅对象observer.trigger('go',{data:"hello",url:'http://wanghai.ml'});
区别
- 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。
- 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
- 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。
- 观察者 模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式。
