观察者模式
观察者模式中有两个重要元素,一个是主体(subject)一个是观察者(observer)。其中主体(subject)有删除,添加和通知等方法。观察者可以去更新等操作。
下面简单实现观察者模式:
js
class Subject{ // 主体
constructor(){
this.observers =[];
}
add(observer){
this.observers.push(observer)
}
remove(observer){
const index = this.observers.findIndex(item=>item===observer)
if(index!=-1){
this.observers.splice(index, 1);
}
}
notify(){
this.observers.forEach(item=>item.update());
}
}
class Observer{ // 观察者
constructor(name){
this.name =name;
}
update(){
console.log(this.name)
}
}
//测试
let subject = new Subject();
let obsDog = new Observer('dog');
let obsCat = new Observer('cat');
sub.add(obsDog);
sub.add(obsCat);
sub.notify();
上述代码中,我们创建了 Subject 对象和两个 Observer 对象,当有关状态发生变更时则通过 Subject 对象的 notify 方法通知这两个 Observer 对象,这两个 Observer 对象通过 update 方法进行更新
发布订阅模式
发布订阅模式 主要有一个调度中心,有订阅,发布,取消订阅等方法。
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码
下面简单实现发布订阅模式
js
class PubSub {
constructor() {
this.subs = {}
}
// 订阅方法
subscribe(key, fb) {
if (!this.subs[key]) {
this.subs[key] = [];
}
this.subs[key].push(fb);
}
// 发布方法
publish(...arg) {
let args = arg;
let key = args.shift(); //取出key值
let fns = this.subs[key];
if(!fns || fns.length<=0) return;
if (this.subs[key]) {
this.subs[key].forEach(cb => cb(...args))
}
}
// 取消订阅方法
unsubscribe(key, cb) {
if (this.subs[key]) {
const cbIndex = this.subs[key].findIndex(e=> e === cb)
if (cbIndex != -1) {
this.subs[key].splice(cbIndex, 1);
}
}
if (this.subs[key].length === 0) {
delete this.subs[key];
}
}
unsubscribeAll(key) {
if (this.subs[key]) {
delete this.subs[key];
}
}
}
// 测试:
const pubSub = new PubSub();
pubSub.subscribe('封神第一部', time => {
console.log(`封神第一部开始时间${time}点`);
})
pubSub.subscribe('封神第二部', time => {
console.log(`封神第二部开始时间${time}点`);
})
pubSub.publish('封神第一部', 7);
pubSub.publish('封神第二部', 11);
通过上面的实现我们发现观察者模式其实是一种直接通讯的方式,比如我们订阅了电影院的微信公众号,当电影院的每种电影上映时,都会对他的所有订阅者发起通知(notify)。
但是在发布订阅模式中多了一个调度中心,比如我们关注了电影院的微信公众号,A同学给电影院发消息只想看封神第一部这个电影,B同学给电影院发消息只想看孤注一掷。那么电影院就会在对应的电影上映时给对应的同学发送不同的消息。,A同学就只接收到封神第一部的开映时间,B同学只接收孤注一掷的开映时间。
总结:
观察者模式有观察者和主体,Subject中通过observers记录ObServer。
优点是:角色明确,Subject和Object要遵循约定的成员方法. 缺点是紧耦合
发布订阅模式有 Publisher发布者、调度中心、Subscribe订阅者,发布者和订阅者不直接通讯,通过调度中心来传递消息。
优点是松散耦合,灵活度高,通常应用在异步编程中, 缺点是:当事件类型变多时,会增加维护成本