这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
1.0版本(双向耦合)
我们描述一个工作做的实际场景来说一说观察者模式,我们在公司的时候会加入很多的群,微信群、QQ群、企业微信群、钉钉群等,他们都有一些公共的功能,第一个功能是可以邀请员工加入,第二个功能是发布群公告来通知群成员。我们员工和工作群之间就形成了符合观察者模式的特点,多位员工关注(订阅)着群公告,工作群在有重要事件的时候进行信息的发布。

WeCharGroup类
| class WeCharGroup { |
| members: Programmer[] = []; |
| notice: string; |
| |
| addMember(member: Programmer): void { |
| this.members.push(member); |
| } |
| |
| setNotice(notice): void { |
| this.notice = notice; |
| } |
| getNotice(): string { |
| return this.notice; |
| } |
| |
| notifyAll(): void { |
| this.members.forEach(v => v.update()); |
| } |
| } |
Programmer类
| class Programmer { |
| name: string; |
| swg: WeCharGroup; |
| |
| constructor(name: string, swg: WeCharGroup) { |
| this.name = name; |
| this.swg = swg; |
| } |
| |
| update() { |
| console.log( |
| `${this.name}您有一条新的群公告,请注意接收!\n${this.swg.getNotice()}` |
| ); |
| } |
| } |
我们通过面向对象的编程思想构造出了WeCharGroup、Programmer两个对象,它们的功能和属性在上面的UML类图和代码中都明确的体现了,我们现在就一起来体验一下吧!
体验进行中
- 第一步:创建我们的工作群。
- 第二步:将公司的前端小张和后端小王邀请入群并让他俩及时获取最新的群公告信息。
- 第三步:今天就是每周的最后一天来,设置一个公告(“下班前记得把周报写完再走。”)。
- 第四步:发布最新公告。
上面的步骤操作完以后,我们的小张和小王就收到了记得写周报的通知,HXD们周报写完了吗?
| |
| const workGroup = new WeCharGroup(); |
| |
| |
| workGroup.addMember(new Programmer('前端小张', workGroup)); |
| workGroup.addMember(new Programmer('后端小王', workGroup)); |
| |
| |
| workGroup.setNotice('下班前记得把周报写完再走。'); |
| |
| |
| workGroup.notifyAll(); |
2.0版本(第一次解耦)
通过看1.0版本的UML类图可以看的出来,我们的微信群看似只能邀请程序员,这怎么能行呢,测试工程师也需要看到公告呀,还有那谁也得看公告的呀。好的我们来针对这个现象进行一次改造吧,我们的需求是什么?多种员工都能在工作群发布公告后通过update
来获取到最新的公告,我们需要将现有的Programmer
类进行抽象封装,因为我们的员工都要对工作群进行关注,所有我们的抽象类定义为Observer。

Observer抽象类
| abstract class Observer { |
| name: string; |
| swg: WeCharGroup; |
| |
| abstract update(): void; |
| } |
Programmer类2.0
| class Programmer extends Observer { |
| constructor(name: string, swg: WeCharGroup) { |
| super(); |
| this.name = name; |
| this.swg = swg; |
| } |
| |
| update() { |
| console.log( |
| `${this.name}您有一条新的群公告,请注意接收!\n${this.swg.getNotice()}` |
| ); |
| } |
| } |
WeCharGroup类2.0
| class WeCharGroup { |
| members: Observer[] = []; |
| ... |
| addMember(member: Observer): void { |
| this.members.push(member); |
| } |
| ... |
| } |
TestEngineer类
| class TestEngineer extends Observer { |
| constructor(name: string, swg: WeCharGroup) { |
| super(); |
| this.name = name; |
| this.swg = swg; |
| } |
| |
| |
| update() { |
| console.log( |
| `${this.name}您有一条新的群公告,请注意接收!\n${this.swg.getNotice()}` |
| ); |
| } |
| } |
体验一下
- 我们在版本1.0的第二步将测试小李邀请入群吧
在我们将观察者抽象出来后不管是我们的测试小李,还是其他岗位的同事我们都可以用最小的改动来满足他们关注群公告的需求了。
| |
| const workGroup = new WeCharGroup(); |
| |
| |
| workGroup.addMember(new Programmer('前端小张', workGroup)); |
| workGroup.addMember(new Programmer('后端小王', workGroup)); |
| |
| workGroup.addMember(new TestEngineer('测试小李', workGroup)); |
| |
| |
| workGroup.setNotice('下班前记得把周报写完再走。'); |
| |
| |
| workGroup.notifyAll(); |
3.0版本(第二次解耦)
在2.0的时候我们支持了不同的员工可以关注工作群里面的公告,但是在实际的职场中我们除了关注公司的微信群很可能关注这公司的企业微信群对不对,或者还有DingDing群,好多的群让人眼花缭乱的,有多少HXD的群组比好友还多的🤔️?再看一下UML类图,我们现在强行的和微信群进行耦合,我们再来改造一把,免得用到的时候手足无措。我们将群组的功能进行抽象命名为Subject。
Subject
| interface Subject { |
| addMember(member: Observer): void; |
| setNotice(notice: string): void; |
| getNotice(): string; |
| notifyAll(): void; |
| } |
DingDingGroup
| class DingDingGroup { |
| members: Observer[] = []; |
| notice: string; |
| |
| addMember(member: Observer): void { |
| this.members.push(member); |
| } |
| |
| setNotice(notice): void { |
| this.notice = notice; |
| } |
| getNotice(): string { |
| return this.notice; |
| } |
| |
| notifyAll(): void { |
| this.members.forEach(v => v.update()); |
| } |
| } |
WeCharGroup3.0
| class WeCharGroup implements Subject { |
| ... |
| } |
Observer2.0
| abstract class Observer { |
| ... |
| swg: Subject; |
| ... |
| } |
Programmer3.0&TestEngineer3.0
| class Programmer extends Observer { |
| constructor(name: string, swg: Subject) { |
| super(); |
| this.name = name; |
| this.swg = swg; |
| } |
| ... |
| } |
| |
| class TestEngineer extends Observer { |
| constructor(name: string, swg: Subject) { |
| super(); |
| this.name = name; |
| this.swg = swg; |
| } |
| ... |
| } |
最后我们在体验一把
- 第一步:创建一个钉钉群
- 第二步:邀请三位同学加入日常群
- 第三步:设置群公告
- 第四步:发布公告
| |
| const everyday = new DingDingGroup(); |
| everyday.addMember(new Programmer('前端小张', everyday)); |
| everyday.addMember(new Programmer('后端小王', everyday)); |
| everyday.addMember(new Programmer('测试小李', everyday)); |
| |
| |
| everyday.setNotice('各位同事周末愉快!!!'); |
| |
| everyday.notifyAll(); |
总结
- 观察者模式也称为发布-订阅模式。
- 观察者模式定义一对多的依赖关系,让多个观察者同时关注一个主题对象,并在主题对象发生变化后通知观察者尽心更新。
注:最近翻了翻好早前买的《大话设计模式》,感觉还有很有意思呀。😯
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)