设计模式-观察者模式

111 阅读2分钟

观察者模式,也称发布-订阅模式,是一种行为型模式,主要用于处理不同对象之间的交互通信问题。

观察者模式中通常会包含两类对象

  1. 一个或多个发布者对象:当有重要的事情发生时,会通知订阅者
  2. 一个或多个订阅者对象:它们追随一个或多个发布者,监听它们的通知,并作出相应的反应。

通常来说,观察者模式可以分为两类:推送和拉动。推送模式是由发布者负责将消息通知给各个订阅者。拉动模式则要求订阅者主动跟踪发布者的状态变化。

观察者对象应该有如下属性和方法

  1. 由回调函数构成的订阅者数组。
  2. 用于添加和删除订阅者的addSubscriber()和removeSubscriber()方法。
  3. publish()方法,接受并传递数据给订阅者。
  4. make()方法,将任意对象转变为一个发布者并为其添加上述方法。
var observer = {
	addSubscriber: function(callback) {
		if (typeof callback === 'function') {
			this.subscribers[this.subscribers.length] = callback
		}
	},
	removeSubscriber: function(callback) {
		for (var i = 0; i < this.subscribers.length; i ++) {
			if (this.subscribers[i] === callback) {
				delete this.subscribers[i]
			}
		}
	},
	publish: function(what) {
		for (var i = 0; i < this.subscribers.length; i++) {
			if (typeof this.subscribers[i] === 'function') {
				this.subscribers[i](what)
			}
		}
	},
	// 将当前对象的方法,赋值给传入的对象。这样观察的对象就有了发布订阅的能力
	make: function(o) {
		for (var i in this){
			if (this.hasOwnProperty(i)){
				o[i] = this[i]
				o.subscribers = []
			}
		}
	}
}

创建订阅者。订阅者是任意对象,它们唯一的职责是在某些重要事件发生的时候调用publish()方法

var blogger = {
	writeBlogPost: function() {
		var content = 'Today is ' + new Date()
		this.publish(content)
	}
}
var la_time = {
	newIssue: function() {
		var paper = 'new Paper'
		this.publish(paper)
	}
}

转变为发布者

observer.make(blogger)
observer.make(la_time)

准备简单对象,待订阅

var jack = {
	read: function(what) {
		console.log('I just read that ' + what)
	}
}
var jill = {
	gossip: function(what) {
		console.log("You don't hear it from me, but " + what)
	}
}

订阅blogger对象,只需要提供事件发生时的回调函数

blogger.addSubscriber(jack.read)
blogger.addSubscriber(jill.gossip)

blogger 写了博客,jack和jill都会收到通知

blogger.writeBlogPost()
// I just read that Today is Sat Jul 27 2019 17:31:41 GMT+0800 (China Standard Time)
// You don't hear it from me, but Today is Sat Jul 27 2019 17:31:41 GMT+0800 (China Standard Time)

取消订阅

blogger.removeSubscriber(jill.gossip)
blogger.writeBlogPost()
// I just read that Today is Sat Jul 27 2019 17:31:41 GMT+0800 (China Standard Time)