废话少说,直接上图

观察者模式(Observer pattern)

顾名思义,观察者模式,就会存在 “被观察者” and “观察者”,两者直接“面对面交流”,不存在任何中间人,为 “松耦合”。

看图: 干饭人在看, 主厨在做,随时准备恰饭 

设计模式 | “观察者”与“订阅发布”_观察者模式

主厨饭菜做好了 (状态发生改变),开始呼叫干饭人,干凡人收到主厨的通知,飞奔过去干饭 (开始工作)

设计模式 | “观察者”与“订阅发布”_观察者模式_02

总结:

设计模式 | “观察者”与“订阅发布”_List_03

订阅发布模式(Publish–subscribe pattern)

订阅发布模式,与 “观察者模式” 不同的是,“订阅者” 与 “发布者” 之间几乎没有见过面,也不认识对方,一切的交流都交由第三方,也就是 “中间人” 完成,属于完全解耦

看图:

设计模式 | “观察者”与“订阅发布”_设计模式_04

看上图可以知道,所有通讯均由 “第三者完成”, 发布者,订阅者,在第三者的任务平台各取所需。而且,无论提前订阅,或者之后订阅,只要发布者任务信息更新,就会通知订阅者。

看图还不明白?看这里给你说道说道

观察者 and 订阅发布 区别

观察者: (观察 | 被观察者)
“观察者”直接观察被“被观察者”,当“被观察者”状态发生改变,
则做出对应反应

订阅发布: (发布者 | 事件调度中心 | 订阅者)
所有事件统一由事件调度中心管理,
“发布者”可以在事件中发布事件,
“订阅者”自主选择订阅消息,
“事件调度中心”接受到对应信息发布,则会通知“订阅者”,途中“事件调度中心”可以做任何处理。

区别:
发布观察者模式中,“观察者”and”被观察者“存在松耦合.
订阅者模式中: 所有处理交由第三者“事件调度中心”(中介),“发布者”and“订阅者”完全解耦

程序实践才是王道,上代码!!!

** 观察者模式**

// 观察者
	class Observer {
		constructor(name) {
			this.name = name;
		}
		// 发现更新
		update() {
			console.log(this.name, ': 我观察的东西更新了。')
			// 执行工作
			this.woke();
		}
		woke() {
			console.log(this.name, ': 开始工作');
		}
	}
	
	// 观察者列表 - 实际作用,封装观察者增删改查
	class ObserverList {
		constructor(arg) {
			this.observerList = [];
		}
	
		addObserver(observer) {
			this.observerList.push(observer)
		}

		remove(observer) {
			this.observerList = this.observerList.filter(item => observer !== item);
		}

		count() {
			return this.observerList.length;
		}

		get(i) {
			return this.observerList[i];
		}
	}
	
	// 目标
	class Subscribe {
		constructor(arg) {
			this.observers = new ObserverList();
		}
		// 增加观察者
		addObserver(observer) {
			this.observers.addObserver(observer);
		}
		// 状态变更通知
		notice() {
			console.log('被人更新了');
			let len = this.observers.count();
			for (let i = 0; i < len; i++) {
				this.observers.get(i).update();
			}
		}
	}
复制代码

订阅发布模式

// 订阅发布模式
 	class EventList {
		constructor() {
			this.events = {};
		}

		subscribe(key, fn) {
			if (!Object.prototype.hasOwnProperty.call(this.events, key)) {
				this.events[key] = [];
			}

			this.events[key].push(fn);
		}

		unSubscribe(key, fn) {
			let eventList = this.events[key];
			if (!eventList || eventList.length == 0) return;
			this.events[key] = this.events[key].filter(f => f !== fn);
		}

		publish(key, ...args) {
			let eventList = this.events[key];
			console.log(key, eventList);
			if (!eventList || eventList.length == 0) return;

			eventList.forEach(f => f(...args))
		}
	}
	
	let ev = new EventList();
	let op = ['123'];
	ev.subscribe(op, (...args) => {
		console.log('t事件执行了', args);
	})

	ev.subscribe(op, args => {
		console.log('t2事件执行了', args);
	})

	ev.publish(op, 123, 5555)
	// -> 't事件执行了' [123, 555]
	// -> 't2事件执行了' 123
复制代码

总结

观察者模式 - 主要是 观察者 和 被观察者 的逻辑实现

订阅发布模式 - 主要是 事件调度中心 的逻辑实现