观察者模式与发布订阅模式

一、观察者模式

定义

观察者模式定义了一个被观察的对象/目标subject和多个观察者observer间的一种一对多的依赖关系,当被观察对象/目标subject的状态发生改变时,所有依赖于它的观察者observer都得到通知并自动更新。(这个被观察的对象/目标可理解为可观察对象 observable

关键字

  • 被观察者 subject 可观察者 observable
  • 观察者 observer

示例

	// 被观察者类
	class Subject {
		constructor() {
			// 用于收集观察者
			this.observerList = []
		}
		
		// 添加观察者
		subscribe(observer) {
			// 存在观察者和观察者的update方法
			if (observer && observer.update) {
				this.observerList.push(observer)
				console.log(`${observer.name}关注了x公众号`)
			}
		}
		
		// 移除观察者
		unsubscribe(observer) {
			this.observerList = this.observerList.filter(c => c !== observer)
			console.log(`${observer.name}取关了x公众号`)
		}
	
		// 被观察者由于某种原因状态改变了,通知所有观察者触发update方法
		notify(article) {
			if (this.observerList.length) {
				this.observerList.forEach(observer => observer.update(article))
				console.log(`x公众号发布文章《${article}》!`)
			}
		}
	}
	
	// 观察者类
	class Observer {
		constructor(name) {
			this.name = name
		}
		update(article) {
			console.log(`${this.name}收到了x公众号发布文章《${article}》的通知`)
		}
	}

	const subject = new Subject()				// 创建一个被观察对象subject,这里指x公众号
	const xiaoMing = new Observer('小明')		// 创建观察者对象,小明
	const xiaoHong = new Observer('小红')		// 创建观察者对象,小红
	
	subject.subscribe(xiaoMing)				// 被观察对象subject,调用subscribe方法添加观察者,形成依赖关系。这里指小明关注x公众号
	subject.subscribe(xiaoHong)				// 被观察对象subject,调用subscribe方法添加观察者,形成依赖关系。这里指小红关注x公众号
	subject.notify('觉醒年代')					// 被观察者由于某种原因状态改变了,触发了notify方法。这里指x公众号发布了文章《觉醒年代》,所有关注该公众号的人都可以收到通知
	subject.unsubscribe(xiaoHong)				// 被观察对象subject,调用unsubscribe方法移除观察者。这里指小红取关x公众号
    subject.notify('中国崛起')					// 由于小红取关了该x公众号,所以当x公众号发布新文章时,小红无法收到通知

二、发布订阅模式

定义

希望接收通知的订阅者subscriber基于自定义通道进行订阅,由中心调度器center统一管理这些自定义通道和对应的订阅者,中心调度器center状态改变时,通过对应的通道向对应的订阅者发布通知,这里自定义通道指发布者publisher

关键字

  • 订阅者 subscriber
  • 中心调度器 center (也称为事件调度器 eventEmitter)
  • 发布者 publisher

示例

	// 中心调度器类
	class Center {
		// 添加向发布者添加订阅者,发布者和订阅者形成依赖关系
		subscribe(subscriber, publisher) {
	        if (!this[publisher.type]) {
	            this[publisher.type] = []
	        }
	        this[publisher.type].push(subscriber)
	        console.log(`${subscriber.name}关注了${publisher.type}`)
	    }
	    
	    // 发布者移除订阅者,解除发布者和订阅者的依赖关系
		unsubscribe(subscriber, publisher) {
			const index = this[publisher.type].findIndex(sub => sub === subscriber)
			if (index !== -1) {
              this[publisher.type].splice(index, 1)
              console.log(`${subscriber.name}取关了${publisher.type}`)
			}
		}
		
		// 发布者发布消息/文章/报刊(状态更新)时,下发通知告诉所有与其有依赖关系的订阅者
		notify(publisher, article) {
			if (this[publisher.type] && this[publisher.type].length) {
				this[publisher.type].forEach(obs => obs.update(publisher.type, article))
				console.log(`${publisher.type}发布文章《${article}》!`)
			}
		}
	}

	// 发布者类
	class Publisher {
		constructor(type) {
			this.type = type
		}
	}	

	// 订阅者类
	class Subscriber {
		constructor(name) {
			this.name = name
		}
		update(type, article) {
			console.log(`${this.name}收到了${type}发布文章《${article}》的通知`)
		}
	}

	const center = new Center()		// 创建中心调度器,统一管理发布者和订阅者
	
	const xiaoMing = new Subscriber('小明')		// 创建订阅者,小明
	const xiaoHong = new Subscriber('小红')		// 创建订阅者,小红
	const xiaoHang = new Subscriber('小航') 	// 创建订阅者,小航
	
	const A = new Publisher('A公众号')	// 创建发布者,A公众号
	const B = new Publisher('B公众号')	// 创建发布者,B公众号
	const C = new Publisher('C公众号')	// 创建发布者,C公众号
	
	center.subscribe(xiaoMing, A)	// 订阅者小明和发布者A公众号形成依赖关系
	center.subscribe(xiaoHong, A)	// 订阅者小红和发布者A公众号形成依赖关系
	center.subscribe(xiaoHang, A)	// 订阅者小航和发布者A公众号形成依赖关系
	center.subscribe(xiaoMing, B)	// 订阅者小明和发布者B公众号形成依赖关系
	center.subscribe(xiaoMing, C)	// 订阅者小明和发布者C公众号形成依赖关系
	
	center.notify(A, '中国人的精神')	// 发布者A公众号发布新文章《中国人的精神》,订阅者小明/小红/小航都可以收到通知
	center.notify(B, '明朝那些事儿')	// 发布者B公众号发布新文章《明朝那些事儿》,订阅者小明可以收到通知
	center.notify(C, '开国大典')		// 发布者C公众号发布新文章《开国大典》,订阅者小明可以收到通知
	center.notify(C, '中国崛起')		// 发布者C公众号发布新文章《中国崛起》,订阅者小明可以收到通知
	
	center.unsubscribe(xiaoHong, A)	// 订阅者小红解除了和发布者A公众号的依赖关系
	center.notify(A, '抗击疫情2020')	// 发布者A公众号发布新文章《抗击疫情2020》,订阅者小明/小航都可以收到通知,小红收不到该通知

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值