设计模式太晦涩,我尽量用简洁的语言描述我对这两个模式的理解,觉得还是有不懂的或者存疑的地方,版聊讨论。
概念
观察者模式广泛应用于JS中。observer观察者是一个集合(collections),当状态有变化的时候,观察者通知集合下的对象相应的改变状态。举例说明这个概念。
代码实例
想象一下你有多个元素,他们需要同时更新内容当一些事件状态发生改变(例如:input中键入文字)。 他们既可以订阅观察者发送的通知,也可以取消观察者发送的通知。 可以在线玩一玩有需要可下载源代码
// define a class
class Observable {
// each instance of the Observer class
// starts with an empty array of things (observers)
// that react to a state change
constructor() {
this.observers = [];
}
// add the ability to subscribe to a new object / DOM element
// essentially, add something to the observers array
subscribe(f) {
this.observers.push(f);
}
// add the ability to unsubscribe from a particular object
// essentially, remove something from the observers array
unsubscribe(f) {
this.observers = this.observers.filter(subscriber => subscriber !== f);
}
// update all subscribed objects / DOM elements
// and pass some data to each of them
notify(data) {
this.observers.forEach(observer => observer(data));
}
}
observer的用例:
// some DOM references
const input = document.querySelector('.js-input');
const p1 = document.querySelector('.js-p1');
const p2 = document.querySelector('.js-p2');
const p3 = document.querySelector('.js-p3');
// some actions to add to the observers array
const updateP1 = text => p1.textContent = text;
const updateP2 = text => p2.textContent = text;
const updateP3 = text => p3.textContent = text;
// instantiate new Observer class
const headingsObserver = new Observable();
// subscribe to some observers
headingsObserver.subscribe(updateP1);
headingsObserver.subscribe(updateP2);
headingsObserver.subscribe(updateP3);
// notify all observers about new data on event
input.addEventListener('keyup', e => {
headingsObserver.notify(e.target.value);
});
与订阅者模式的对比
pub-sub模式多了一步publisher,它动态的接受着event
function pubSub() {
const subscribers = {}
function publish(eventName, data) {
//没有订阅直接返回
if (!Array.isArray(subscribers[eventName])) {
return
}
//有订阅挨个执行函数
subscribers[eventName].forEach((callback) => {
callback(data)
})
}
function subscribe(eventName, callback) {
if (!Array.isArray(subscribers[eventName])) {
subscribers[eventName] = []
}
subscribers[eventName].push(callback)
}
return {
publish,
subscribe,
}
}
pub-sub最核心的代码就是这段,和observer的区别如下:
- 明显看出来和observer收集的数据结构就是不一样的,observer收集的是function,pubsub收集的是个object,{ eventName:callback }
- pubsub通过publish增加了一个动态的添加入口,observer是hardcore好的集合是死的。
总结:为什么要了解它
其实随着Vue和React这些响应式框架的流行,observer设计模式已经不太需要自己去写原生代码了,但原生代码会告诉你一些第一性原则,比如:
- observer是函数的collection
- publisher是对象的collection
- 如果是collection那么它也是iterator,都可以作为数据流来处理
那么UI events(click,mousemove等等)它们是observers,它们都可以当作数据流,瞬间有了一种天灵盖被钻孔的感觉。这可以更好的消除代码中的bug,提高质量和效率。
注这部分有点深,英语能力好的同学可以先参考我找到的资料。