今天要谈到的观察者模式也是很常见的一个模式,常出现在有两个以上需要互相沟通的物件之间
假设有个物件 A 想要获得物件 B 的更新资讯,但实际上 A 不知道 B 哪时候才会更新。这时候 A 可以做的事情就是,不断地向 B 发出请求然後拿回资讯。或者,就让 B 把资讯广播到系统当中,让所有系统当中的物件都可以接收到最新的资讯。
但以上两种都不是理想的做法。最好的情况会是,B 知道 A 在等他,所以一旦更新资讯的时候,B 就可以主动通知 A。
以现实生活中的例子来说,就是某个消费者想要获得某个品牌的最新资讯,就会加入这个品牌的会员。而当这个品牌有新产品上市或有新的折扣的时候,就会找出他的「会员名单」,然後一一通知他们
在观察者模式当中有两个主体,分别是 Subject
和 Observer
,可以想像就是先前提到的「会发出通知的品牌」和「想要收到通知的消费者」
所以在 Subject
当中,有可以将消费者加入名单,或从名单中移除的方法。在 Observer
当中,则有个 update
方法可以呼叫
interface Subject {
attach(observer: Observer): void
detach(observer: Observer): void
notify(): void
}
interface Observer {
update(subject: Subject): void;
}
接下来就让我们根据介面来建立类别。
这里我就不用刚刚的品牌和消费者的例子,而是建立一个特务机构 SecretIntelligenceService
,并实作出各种方法的细节
class SecretIntelligenceService implements Subject {
private observers: Observer[] = [];
message: string;
attach(observer: Observer): void {
if (this.observers.includes(observer)) {
return
}
this.observers.push(observer)
}
detach(observer: Observer): void {
this.observers = this.observers.filter(o => o !== observer)
}
notify(): void {
this.observers.forEach(observer => observer.update(this))
}
updateInfo(message: string): void {
this.message = message
this.notify()
}
}
而在 Observer
这边,我们建立了 Agent
类别,以及 update
方法的细节
class Agent implements Observer {
name: string
constructor(name: string) {
this.name = name
}
update(info: SecretIntelligenceService): void {
console.log(`${this.name} received update: ${info.message}`)
}
}
那麽最後,我们就可以来建立实例
const mi6 = new SecretIntelligenceService()
const james = new Agent('james')
const bond = new Agent('bond')
mi6.attach(james)
mi6.attach(bond)
mi6.attach(james) // james 不会被重复加入
实际执行结果如下:
mi6.updateInfo('no time to die')
// james received update: no time to die
// bond received update: no time to die
mi6.detach(james)
mi6.updateInfo('shaken, not stirred')
// bond received update: shaken, not stirred
观察者模式解决了我们先前提到的问题,并在物件之间建立起沟通的管道,让物件之间的合作能够更为顺畅。只不过目前所有的 obervers 都会同时接收到更新资讯,如果我们希望 obervers 有层级之分、有先後收到资讯的分别,那麽就需要额外的处理,或是使用其他的模式来解决问题了
>>: [Day30]ISO 27001 附录 A.18 遵循性
前言 本文说明取得历史交易资料。 K棒说明 程序实作 取得历史K棒资料 # 取得历史K棒资料 # 资...
元件介绍 FormControl 让我们可以将 form input 所需要的共同前後文特性独立出来...
Angular [目标] 启动程序先导入Login元件 1. 新增元件、模组 Syntax:ng h...
链接串列(Linked List) 链接串列是一种线性表,使用Pointer串接资料,好处是找到目标...
今天在学习3d建模的时候,发现一个有趣的东西:3d建模的模型,如果要方便使用在各种软件当中的话,需要...