观察者模式
观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。
观察者模式有一个别名叫“发布-订阅模式”,订阅者和订阅目标是联系再一起的,当订阅目标发生改变时,逐个通知订阅者。
发布/订阅模式
在24种基本的设计模式中并没有发布订阅模式,是观察者模式的一个别称。
但是经过时间的沉淀,似乎更加强大了起来,已经独立于观察者模式,成为另外一种不同的设计模式。
在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者并不知道彼此的存在。在发布者和订阅者之间存在第三方组件,成为调度中心或者事件通道,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应的分发他们给订阅者。
区别
可以看出,发布订阅模式相比观察者模式多了个事件通道,事件通道作为调度中心,管理事件的订阅和发布工作,彻底隔绝了订阅者和发布者的依赖关系。即:订阅者在订阅事件的时候,只关注事件本身,而不关系谁会发布这个事件;发布者在发布事件的时候,只关注事件本身,而不关注谁订阅了这个事件。
观察者模式有两个重要的角色,即:目标和观察者。在目标和观察者之间是没有事件通道的。一方面,订阅者想订阅目标事件,由于没有事件通道,因此必须将自己添加到目标中进行管理;另一方面,目标在触发事件的时候,也无法知道操作委托给事件通道,因此只能亲自去通知所有的观察者。
发布订阅模式示例
class pubSub {
constructor() {
this.subscribers = [];
}
subscribe(topic, callback) {
let callbacks = this.subscribers[topic];
if (!callbacks) {
this.subscribers[topic] = [callback];
} else {
callbacks.push(callback);
}
}
publish(topic, ...args) {
let callbacks = this.subscribers[topic] || [];
callbacks.forEach(callback => {
callback(...args);
})
}
}
let pub = new pubSub();
pub.subscribe('SMS', () => console.log("OK"));
pub.subscribe('SMS', () => console.log("OKOK"));
pub.publish("SMS");
订阅者只要订阅相关信息就好,谁发布可以不用关心。
观察者模式示例
class Subject {
constructor() {
this.observers = [];
}
add(observer) {
this.observers.push(observer);
}
notify(...args) {
this.observers.forEach(observer => observer.update(...args));
}
}
class Observer {
constructor(callback) {
this.callback = callback;
}
update(...args) {
this.callback(...args);
}
}
let person1 = new Observer(_ => console.log("OK"));
let person2 = new Observer(_ => console.log("OK"));
let sub = new Subject();
sub.add(person1);
sub.add(person2);
sub.notify();
需要创建观察者手动通知。