JavaScript - 观察者模式的实现与应用场景

1. 什么是观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系。当主题带有的状态被改变时,所有观察者都会收到通知并自动更新。

主题(Subject):Subject也可以称为被观察者,它维护一个Observer列表,实现新增、删除、通知Observer更新的方法。

观察者(Observer):Observer是接收主题通知的对象,需要实现一个更新方法,当收到Subject的通知时,调用该方法进行更新。

具体主题(Concrete Subject):ConcreteSubject继承了Subject,是Subject的具体实现类,我们在其中定义主题状态,当状态发生某些变化时通知Observer更新。

具体观察者(Concrete Observer):ConcreteObserver是Observer的具体实现类。它定义了在收到通知时需要执行的具体操作。

需要注意的是,在观察者模式的依赖关系中,并不是观察者主动拉取主题消息,而是被动的接收主题通知并产生相应变化

2. 观察者模式举例

以拍卖会上拍卖者与竞价者的一对多的依赖关系举例:当价格更新时,所有的竞价者都会收到通知。

3. 例子的代码实现

定义Subject类与Observer类

javascript 复制代码
/**
 * 主题(Subject)中维护一个观察者列表,实现新增、删除观察者、与通知观察者更新的方法
 */
class Subject {
  constructor() {
   this.observerList = [];
  }
  
  /**
   * 新增观察者方法
   * @param observer
   */
  addObserver(observer) {
   this.observerList.push(observer);
  }
  
  /**
   * 移除观察者方法
   * @param observer
   */
  removeObserver(observer) {
   const findBidderIndex = this.observerList.findIndex(observerItem => {
    return observerItem.id === observer.id;
   })
   if(findBidderIndex > -1) {
    this.observerList.splice(findBidderIndex, 1);
   }
  }
  
  /**
   * 通知观察者进行更新
   * @param data
   */
  notify(data) {
   this.observerList.forEach(observerItem => {
    observerItem.update(data);
   })
  }
}

/**
 * 观察者(Observer)中应定义一个更新方法
 */
class Observer {
  
  /**
   * 更新方法
   * @param data
   */
  update(data) {
  }
}

定义Subject与Observer的具体类

scala 复制代码
/**
 * 定义一个拍卖师类,作为具体主题(ConcreteSubject)
 */
class Auctioneer extends Subject {
  constructor() {
   super();
   this.state = '30';
  }
  
  setState(state){
   this.state = state;
   this.notify(this.state);
  }
  
  getState(){
   return this.state;
  }
}

/**
 * 定义一个竞拍者类,作为具体观察者(ConcreteObserver),实现update方法
 */
class Bidder extends Observer {
  constructor(id) {
   super();
   this.id = id;
  }
  
  update(data) {
   console.log('竞拍者 ' + this.id + ' 收到通知:' + data);
  }
}

创建实例、修改状态

ini 复制代码
//实例化具体主题
const auctioneer = new Auctioneer();

//实例化具体观察者
const bidder1 = new Bidder(1);
const binder2 = new Bidder(2);
const binder3 = new Bidder(3);

//将具体观察者推入具体观察者列表
auctioneer.addObserver(bidder1);
auctioneer.addObserver(binder2);
auctioneer.addObserver(binder3);
auctioneer.removeObserver(binder2);

//修改状态
auctioneer.setState(20);

打印结果

复制代码
竞拍者 1 收到通知:20
竞拍者 3 收到通知:20

4.观察者模式的适用场景

当目标对象与其它对象产生一对多关系时,当目标对象改变,希望其它对象也发生相应变化

比如在订单页面使用v-for生成出来几个Tab组件,通过滑动切换。这些Tab页标识着该用户所有订单的状态。

当用户操作的某一笔订单的状态发生改变时,我们希望每个与该笔订单相关的所有Tab组件都发生变化,都重新走一遍查询接口。

这时就可以定义这一组一对多的依赖,将相关标签页的key推入Store中定义的列表作为状态。使用观察者模式使那些存于列表中的Tab刷新。

相关推荐
慧都小项22 分钟前
从 Figma 到 Qt:Qtitan 能减少哪些界面还原工作?
前端·qt·嵌入式·figma·图形界面·工业界面·qtitan
YWL25 分钟前
OpenLayers导出功能:地图截图+GeoJSON导出完整方案,从Canvas合并到PDF生成
前端·vue·openlayers
苦瓜小生33 分钟前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
mayaairi43 分钟前
Vue2 实战进阶:表单数据收集、指令系统与自定义指令全解析
前端·javascript·vue.js
计算机魔术师1 小时前
实测GPT-6 Astra后,我发现过去十年的专业门槛正在失效
前端
虎头金猫1 小时前
Pic Smaller 本地部署:压缩图片、转换格式,再搭建自己的 Web 工具
运维·前端·开源·aigc·ai编程·ai写作
hunterandroid1 小时前
Android ANR 排查实战:从线上告警到主线程卡点定位
android·前端
图扑软件1 小时前
下篇・换墨|主题/多语言/移动端,一套组件全覆盖
前端·javascript·ui·性能优化·数据可视化
程序员老赵1 小时前
Docker 部署 TeX Live:轻松搭建 LaTeX 论文排版编译平台
前端·docker·latex
Zhu7581 小时前
部署安全的pg数据库,搭配pgadmin实现web界面管理
前端·数据库·安全