发布——订阅模式
发布者 <——> 消息代理(即下例中的event_bus) <——> 订阅者
发布者向消息代理发送不同类型的消息,订阅者则从消息代理选择想要订阅的消息类型(发布和订阅不互相依赖,通过中间的消息代理通信)
class EventBus(){
constructor()(
//events的键是所有发布的事件,值是对应事件的订阅者们(的订阅回调行为)
this.events = {}
)
//订阅(对某一事件订阅)
subscribe(event_name, subscribe_cb){
if(!this.events[event_name]) this.events[event_name] = []
this.events[event_name].push(subscribe_cb)
}
//发布(某一事件发布相关args,该事件的订阅者们使用该args完成自己的回调行为)
publish(event_name, ...args){
if(!this.events[event_name]) return
else{
this.events[event_name].forEach(cb => {
//此处具体情况具体分析
cb(...args)
})
}
}
//取消订阅
unsubscribe(event_name, subscribe_cb){
if(!this.events[event_name]) return
const subscribe_cbs = events[event_name]
const idx = subscribe_cbs.indexOf(subscribe_cb)
if(idx !== -1) subscribe_cbs.splice(idx, 1)
}
//撤回发布
unpublish(event_name){
delete this.events[event_name]
}
}
let event_bus = new EventBus()
观察者模式
发布者知道所有订阅者,会自动进行消息推送。被观察者和观察者是一对多的依赖关系
class Observer(){
constrctor(name){
this.name = name
}
update(subject){
console.log(`${this.name},当前你观察的对象的状态是${subject.get_state()}`);
//进行系列操作
}
}
class Subject(){
constructor(){
this.state = {}
this.observers = []
}
add(observer){
this.observers.push(observer)
}
remove(observer){
const idx = this.observers.indexOf(observer)
if(idx !== -1) this.observers.splice(idx, 1)
}
notify(){
this.observers.forEach(observer => observer.update(this))
}
get_state(){
return this.state
}
set_state(new_state){
this.state = new_state
this.notify()
}
}
//两个舔狗时刻观察着女神的朋友圈
let tiangou1 = new Observer('舔狗1号')
let tiangou2 = new Observer('舔狗2号')
let nvshen = new Subject()
nvshen.add(tiangou1)
nvshen.add(tiangou2)
//女神发朋圈说今天好难过,这时舔狗1、2号均会接受到此消息
nvshen.set_state({'mood':'sad'})
观察者模式更标准的做法是:把Observer类作为父类供观察者们继承——子类可以重写update方法进行个性化操作;同时可以把Subject类作为抽象接口——把obervers属性、add、remove、notify三个方法抽离出来,而具体被观察类保存有自己的内部状态,比如:
class TianGou1 extends Observer{
update(subject){
//给女神买蜜雪冰城
}
}
class TianGou2 extends Observer{
update(subject){
//给女神买茶颜悦色
}
}
class NvShen extends Subject(){
//女神独有的状态和方法
}
总结
两种模式的不同可以这样理解:观察者模式——你订了报社的报纸,每当有新报纸报社就会自己给你送来; 发布-订阅模式——公告栏上会更新信息,你需要自己去看