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刷新。

相关推荐
roamingcode1 小时前
Claude Code NPM 包发布命令
前端·npm·node.js·claude·自定义指令·claude code
码哥DFS1 小时前
NPM模块化总结
前端·javascript
灵感__idea2 小时前
JavaScript高级程序设计(第5版):代码整洁之道
前端·javascript·程序员
唐璜Taro2 小时前
electron进程间通信-IPC通信注册机制
前端·javascript·electron
陪我一起学编程3 小时前
创建Vue项目的不同方式及项目规范化配置
前端·javascript·vue.js·git·elementui·axios·企业规范
LinXunFeng4 小时前
Flutter - 详情页初始锚点与优化
前端·flutter·开源
GISer_Jing4 小时前
Vue Teleport 原理解析与React Portal、 Fragment 组件
前端·vue.js·react.js
Summer不秃4 小时前
uniapp 手写签名组件开发全攻略
前端·javascript·vue.js·微信小程序·小程序·html
coderklaus4 小时前
Base64编码详解
前端·javascript
NobodyDJ5 小时前
Vue3 响应式大对比:ref vs reactive,到底该怎么选?
前端·vue.js·面试