观察者模式: 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。
发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
![](https://img.haomeiwen.com/i4642829/2ee41155c633e192.png)
使用观察者模式,面向接口编程,实现松耦合。
发布订阅模式里,发布者和订阅者,不是松耦合,而是完全解耦的
- 从表面上看:
观察者模式里,只有两个角色 —— 观察者 + 被观察者
而发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker
- 往更深层次讲:
观察者和被观察者,是松耦合的关系
发布者和订阅者,则完全不存在耦合
- 从使用层面上讲:
观察者模式,多用于单个应用内部
发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件
// 观察者模式
// 观察者列表
function ObserverList () {
this.observerList = [];
}
ObserverList.prototype.add = function (obj) {
return this.observerList.push(obj);
}
ObserverList.prototype.count = function () {
return this.observerList.length;
}
ObserverList.prototype.get = function (index) {
if (index > -1 && index < this.observerList.length) {
return this.observerList[index];
}
}
ObserverList.prototype.indexOf = function (obj, startIndex) {
var i = startIndex || 0;
while (i < this.observerList.length) {
if (this.observerList[i] === obj) {
return i;
}
i++;
}
return -1;
}
ObserverList.prototype.removeAt = function (index) {
this.observerList.splice(index, 1);
}
// 目标
function Subject () {
this.observers = new ObserverList();
}
Subject.prototype.addObsever = function (observer) {
this.observers.add(observer);
}
Subject.prototype.removeObsever = function (observer) {
this.observers.removeAt(this.observers.indexOf(observer, 0));
}
Subject.prototype.notify = function (context) {
var observerCount = this.observers.count();
for(var i = 0; i < observerCount; i++) {
this.observers.get(i).update(context);
}
}
// 观察者
function Observer () {
this.update = function (context) {
console.log(context);
}
}
var mySubject = new Subject();
mySubject.addObsever(new Observer);
mySubject.notify("hello world");
// 发布订阅模式
var Event = (function() {
var obj = {},
listen,
trigger,
remove;
// 订阅
listen = function(key, fn) {
if (!obj[key]) {
obj[key] = []
}
obj[key].push(fn)
}
// 发布 触发
trigger = function() {
// 获取key
var key = Array.prototype.shift.call(arguments)
// 如果没有订阅过 直接返回
var fnList = obj[key]
if (!fnList || fnList.listen === 0) {
return
}
// 遍历 订阅过的函数列表 分别触发
for (var i in fnList) {
// 执行函数 并把去掉key之后的参数传入
fnList[i].apply(this, arguments)
// fnList[i](...arguments)
}
}
// 移除监听如果没有传入 fn .把key所有的监听移除
remove = function(key, fn) {
var fnList = obj[key]
if (!fnList) {
return
}
if (!fn) {
fnList.length = 0
} else {
for (var i in fnList) {
if (fnList[i] == fn) {
fns.splice(i, 1)
}
}
}
}
return {
listen,
trigger,
remove
}
})()
Event.listen('test', function(a, b) {
console.log('监听test', a, b);
})
setTimeout(() => {
Event.trigger('test', 111, 222)
}, 2000)
网友评论