共计 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
事件中的dispatchEvent
和addEventListener
;
毛病
- 当事件类型越来越多时,难以保护,须要思考事件命名的标准,也要防备数据流凌乱。
实现
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),比方消息中间件;
正文完