JS设计模式——观察者模式

什么是观察者模式?

一个或多个观察者对目标的状态感兴趣,它们通过将自己依附在目标对象上以便注册所感兴趣的内容。
目标状态发生改变并且观察者可能对这些改变感兴趣,就会发送一个通知消息,调用每个观察这的更新方法。
当观察者不再对目标状态感兴趣时,他们可以简单地将自己从中分离。

看完后你会觉得这是什么破玩意?不要急,我们举个现实中的例子,来按段落顺序逐步分解下上面这段话的意思。

去饭馆吃饭,点完餐会给你一个号码,然后就和其余点完餐的人一样,坐着等叫号。

每当做好一份餐,服务员就会喊多少号的餐好了。然后每个人都会收到这个消息,并开始检查自己手里的号,看是不是自己的餐好了,如果是自己的餐,就不要坐着了,赶紧去吃饭了。

有些人等着等着,觉得不想吃了,可能是嫌做饭太慢气饱了,就离开不吃了。
抽象组件

我们把上面这个场景再简化抽象成 JS 描述。

比如,一个 JS 对象 O 被修改了,那么它就需要自动通知那些依赖它的对象。这里所有依赖对象 O 的对象都是观察者,而对象 O 就是一个目标。
在这里插入图片描述
根据这个图,我们就可以假设对象 O 都是通过目标类(Subject Class)实例化出来的,而依赖对象 O 的那些对象都是通过观察者类(Observer Class)实例化出来的。

那么我们就可以抽象出来 4 个组件:

目标(Subject)
维护一系列的观察者,方便添加或删除观察者。对应一个目标类,提供一些注册和通知观察者的接口。

观察者(Observer)
在目标状态发生改变时,为需要得到通知的对象提供一个更新接口。对应一个观察者类,提供一个更新观察者状态的接口。

具体目标(ConcreteSubject)
状态发生改变时,向 Observer 发出通知,存储 ConcreteObserver 的状态。对应一个目标实例。

具体观察者(ConcreteObserver)
存储一个指向 ConcreteSubject 的引用,实现 Observer 类的更新接口,以是自身状态与目标状态保持一致。对应一个观察者实例。

实现

1、为了管理观察者,我们先实现一个 ObserverList 类。也就是一个数组结构,并提供一些常用的数组操作接口。

class ObserverList {
	constructor() {
		this.observerList = []
	}
	add(obj) {
		return this.observerList.push(obj)
	}
	get(index) {
		if (index > -1 && index < this.observerList.length) {
			return this.observerList[index]
		}
	}
	count() {
		return this.observerList.length
	}
	remove(index) {
		this.observerList.splice(index, 1)
	}
	indexOf(obj) {
		return this.observerList.indexOf(obj)
	}
}

2、目标类。提供注册和通知观察者等接口。

3、Observer 类。提供一个观察者更新接口。

class Observer {
	update() {
		// ...
	}
}

以上便是观察者模式的实现方式。
使用

下面我们来看下观察模式的使用,我们继续前面饭馆吃饭的场景。

<button id="callClient">Call</button>
// 先实例化一个饭馆
const restaurant = new Subject()

// 实例化两个顾客 a 和 b
const a = new Observer()
const b = new Observer()

// 定义当前被叫号的顾客
let currentObserver

/**
* @desc a 顾客实现自己的更新方法
* @params restaurant 饭堂实例
*/ 
a.update = function(restaurant) {
	// 判断当前的叫号是不是自己
    if (restaurant.observers.get(0) == a) {
        console.log('我是a,我的饭好了')
        // 如果是自己,把当前叫号的顾客赋值成自己
        currentObserver = a
    }
}

// a 顾客实现自己的更新方法
b.update = function(restaurant) {
	// 判断当前的叫号是不是自己
    if (restaurant.observers.get(0) == b) {
        console.log('我是b,我的饭好了')
        // 如果是自己,把当前叫号的顾客赋值成自己
        currentObserver = b
    }
}

// 两位顾客先后在饭堂点餐,把自己注册为观察者
restaurant.addObserver(a)
restaurant.addObserver(b)

// 绑定通知,每次点击通知所有顾客,餐好了
callClient.onclick = function() {
	// 饭好了,通知所有顾客
    restaurant.notify(restaurant)
    // 把拿走饭的顾客,移除,不需要关心了
    restaurant.removeObserver(currentObserver)
}

以上就是一个模拟场景,应用了观察者模式。如果有不正确的地方,望指出。

作者:userkang
来源:CSDN
原文:https://blog.csdn.net/userkang/article/details/86717726
版权声明:本文为博主原创文章,转载请附上博文链接!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值