当前位置: 首页 > article >正文

用JavaScript实现观察者模式

  1. 观察者模式定义:是一种行为设计模式,定义了一对多的依赖关系,主题对象状态变化时会通知所有观察者对象,使其自动更新。
  2. JavaScript 实现示例
    • 主题类(Subject):维护观察者数组,提供添加(addObserver)、移除(removeObserver)和通知(notifyObservers)观察者的方法。
    • 观察者类(Observer):定义update方法,在接收到通知时被调用。
    • 使用示例:创建SubjectObserver实例,添加观察者,通知观察者,移除观察者后再次通知,展示了观察者模式的基本流程。
  3. 优缺点
    • 优点:解耦观察者和被观察者;支持运行时动态添加或移除观察者;实现广播通信;是事件驱动架构的基础;可支持多种观察者。
    • 缺点:大量观察者时通知可能导致性能下降;存在循环依赖风险;缺乏变化细节,增加实现复杂性。
  4. 实际应用场景
    • GUI 事件监听:如 Web 开发中的 DOM 事件监听,按钮点击等事件处理。
    • 数据模型与视图同步:在 MVC 架构及 Vue.js、React 等框架中,实现数据模型变化时视图自动更新。
    • 发布 - 订阅系统:消息中间件(如 Kafka、RabbitMQ)和社交媒体平台采用该机制,发布者发布消息,订阅者接收通知处理。
    • 金融系统监控:股票市场监控系统中,投资者作为观察者订阅股票,股价变动时接收通知决策。
    • 缓存系统的失效通知:分布式系统中,缓存数据失效时通知相关系统或服务更新或重新加载数据。

 示例:

  1. 简单的事件发布 - 订阅系统
// 定义一个主题类(Subject)
class Subject {
  constructor() {
    this.observers = [];
  }
  // 添加观察者
  addObserver(observer) {
    this.observers.push(observer);
  }
  // 移除观察者
  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index > -1) {
      this.observers.splice(index, 1);
    }
  }
  // 通知所有观察者
  notifyObservers(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}
// 定义一个观察者类(Observer)
class Observer {
  constructor(name) {
    this.name = name;
  }
  // 更新方法,在接收到通知时调用
  update(data) {
    console.log(`${this.name} received data: ${data}`);
  }
}
// 使用示例
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
subject.addObserver(observer1);
subject.addObserver(observer2);
// 通知观察者
subject.notifyObservers('Hello Observers!');
// 移除一个观察者
subject.removeObserver(observer1);
// 再次通知观察者(此时只通知 observer2)
subject.notifyObservers('Hello Remaining Observer!');

在这个示例中,Publisher类充当主题角色,subscribeunsubscribepublish方法分别用于管理订阅者、取消订阅和发布事件通知订阅者。 

 

2. 模拟游戏角色状态变化通知 

// 游戏角色类(被观察者)
class GameCharacter {
    constructor(name) {
        this.name = name;
        this.health = 100;
        this.observers = [];
    }
    // 添加观察者
    addObserver(observer) {
        this.observers.push(observer);
    }
    // 移除观察者
    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index > -1) {
            this.observers.splice(index, 1);
        }
    }
    // 通知观察者
    notifyObservers() {
        this.observers.forEach(observer => observer.update(this.name, this.health));
    }
    // 受到伤害方法
    takeDamage(damage) {
        this.health -= damage;
        console.log(`${this.name} 受到 ${damage} 点伤害,剩余生命值: ${this.health}`);
        this.notifyObservers();
    }
}

// 观察者类
class CharacterObserver {
    constructor(name) {
        this.name = name;
    }
    // 更新方法
    update(characterName, health) {
        console.log(`${this.name} 观察到 ${characterName} 的生命值变为: ${health}`);
    }
}

// 使用示例
const character = new GameCharacter('战士');
const observer1 = new CharacterObserver('玩家1');
const observer2 = new CharacterObserver('玩家2');
character.addObserver(observer1);
character.addObserver(observer2);
character.takeDamage(20);
character.removeObserver(observer1);
character.takeDamage(10);

该示例中,GameCharacter类表示游戏角色,当角色受到伤害时会通知所有观察者,展示了观察者模式在游戏开发中角色状态监控方面的应用。 


http://www.kler.cn/a/525025.html

相关文章:

  • QPS 值是怎样进行计算和应用的
  • 青少年编程与数学 02-008 Pyhon语言编程基础 07课题、数字
  • 【Go语言圣经】第五节:函数
  • [C语言日寄] <stdio.h> 头文件功能介绍
  • Haproxy入门学习二
  • CMAKE工程编译好后自动把可执行文件传输到远程开发板
  • 小白爬虫冒险之反“反爬”:无限debugger、禁用开发者工具、干扰控制台...(持续更新)
  • 【16届蓝桥杯寒假刷题营】第2期DAY4
  • 安卓逆向之脱壳-认识一下动态加载 双亲委派(二)
  • 洛谷P3383 【模板】线性筛素数
  • 在Visual Studio Code自带的按键编译无法使用该怎么办
  • JavaScript_01
  • Baklib如何重新定义企业知识管理提升组织效率与创新力
  • MyBatis 缓存机制详解
  • Java学习教程,从入门到精通,JDBC 删除表语法及案例(103)
  • 基于Langchain-Chatchat + ChatGLM 本地部署知识库
  • 240. 搜索二维矩阵||
  • 【JavaEE】Spring(6):Mybatis(下)
  • docker安装emqx
  • 11JavaWeb——SpringBootWeb案例02
  • S4 HANA明确Tax Base Amount是否考虑现金折扣(OB69)
  • 蓝桥杯python语言基础(4)——基础数据结构(下)
  • 洛谷P11464 支配剧场
  • 深度学习框架应用开发:基于 TensorFlow 的函数求导分析
  • SpringSecurity:There is no PasswordEncoder mapped for the id “null“
  • Kotlin 委托详解