javascript如何实现设计模式_单例模式和观察者模式如何写


单例模式确保类唯一实例并提供全局访问,核心是延迟初始化与实例缓存;观察者模式实现一对多依赖通知,含Subject与Observer角色,需注意内存泄漏与取消订阅。

单例模式确保一个类只有一个实例,并提供全局访问点;观察者模式定义对象间一对多依赖,当一个对象状态改变,所有依赖者自动收到通知。两者在 JavaScript 中实现简洁但需注意细节。

单例模式:用闭包或类+静态属性控制实例唯一性

核心是“延迟初始化 + 实例缓存”。避免每次 new 都创建新对象。

  • 传统闭包写法(兼容性好):

    const Singleton = (function() {
      let instance;
      function createInstance() {
        return {
          data: [],
          add(item) { this.data.push(item); },
          get() { return this.data; }
        };
      }
      return {
        getInstance() {
          if (!instance) {
            instance = createInstance();
          }
          return instance;
        }
      };
    })();
    // 使用
    const a = Singleton.getInstance();
    const b = Singleton.getInstance();
    console.log(a === b); // true
  • ES6 Class 写法(更现代):
    class Logger {
      static #instance;
      constructor() {
        if (Logger.#instance) {
          throw new Error("Already instantiated");
        }
        Logger.#instance = this;
      }
      static getInstance() {
        if (!Logger.#instance) {
          new Logger();
        }
        return Logger.#instance;
      }
      log(msg) { console.log("[LOG]", msg); }
    }
    // 使用
    const logger1 = Logger.getInstance();
    const logger2 = Logger.getInstance();
    console.log(logger1 === logger2); // true

观察者模式:手动实现发布-订阅机制

关键角色:Subject(被观察者)、Observer(观察者)。不依赖第三方库,纯 JS 就能搭出轻量通信总线。

  • 基础版 Subject 类:
    class EventTarget {
      constructor() {
        this.observers = new Map();
      }
      subscribe(event, callback) {
        if (!this.observers.has(event)) {
          this.observers.set(event, new Set());
        }
        this.observers.get(event).add(callback);
      }
      unsubscribe(event, callback) {
        if (this.observers.has(event)) {
          this.observers.get(event).delete(callback);
        }
      }
      notify(event, data) {
        if (this.observers.has(event)) {
          for (const cb of this.observers.get(event)) {
            cb(data);
          }
        }
      }
    }
    // 使用示例
    const bus = new EventTarget();
    bus.subscribe("user-login", (user) => console.log("欢迎", user.name));
    bus.subscribe("user-login", (user) => console.log("更新头像"));
    bus.notify("user-login", { name: "张三" });
  • 进阶建议:
    – 用 WeakMap 存 observer 可避免内存泄漏(尤其 DOM 元素作为 observer 时)
    – 加入 once 方法支持一次性监听
    – notify 支持异步(如 Promise.all)避免阻塞主线程

实际用在哪?别硬套,看场景

单例适合:全局配置管理、日志器、状态仓库(如简易版 store)、WebSocket 连接实例。
观察者适合:组件通信(尤其无框架时)、表单联动、事件解耦(比如按钮点击后多个模块响应)、状态变更广播。

基本上就这些。两种模式都不复杂,但容易忽略边界情况——比如单例没防 new,观察者没做取消订阅,上线后可能悄悄吃内存。


# javascript  # es6  # java  # js  # websocket 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Windows11如何设置专注助手_Windows11专注助手使用攻略【技巧】  php下载安装后memory_limit怎么设置_内存限制调整【技巧】  Golang如何测试HTTP中间件_Golang HTTP中间件功能测试实践  Python抽象类与接口设计_规范说明【指导】  Windows 10怎么隐藏特定更新补丁_Windows 10使用微软官方工具wushowhide.diagcab  Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】  Python与MongoDB NoSQL开发实战_文档模型与索引优化  mac怎么安装字体_MAC添加第三方字体与字体册管理【教程】  如何使用Golang实现微服务状态监控_Golang服务运行状态采集方法  如何使用Golang匿名函数_快速定义临时函数逻辑  WindowsUSB驱动安装异常怎么办_USB驱动重建与恢复教程  Win11如何卸载OneDrive_Win11卸载OneDrive方法【教程】  Go 中的 := 运算符:类型推导机制与使用边界详解  如何使用Golang实现多重错误处理_Golangerror组合与判断方法  Win10如何优化内存使用_Win10内存优化技巧【攻略】  php订单日志怎么导出excel_php导出订单日志到表格教程【教程】  MAC怎么设置程序窗口永远最前_MAC窗口置顶插件安装与快捷设置【方法】  Win11文件扩展名怎么显示_Win11查看文件后缀名设置【基础】  如何使用Golang sync.Map实现并发安全map_避免锁竞争  Win11怎么设置指纹解锁 Win11笔记本录入指纹登录【教程】  VSC怎么在PHP中调试MySQL_数据库交互排查技巧【教程】  Go语言中正确反序列化多个同级XML元素为结构体切片的方法  Win11怎么更改系统语言_Win11中文语言包下载与安装【指南】  Win11怎么设置环境变量_Win11配置Path路径变量【详解】  PHP 中如何在函数内持久化修改引用变量的指向  Win11截图快捷键是什么_Win11自带截图工具使用技巧【汇总】  Python项目回滚策略_发布安全说明【指导】  Win11怎么关闭系统推荐内容_Windows11开始菜单布局设置  Win11怎么设置应用分屏_Windows11贴靠布局Snap Layouts  Win11怎么自动隐藏任务栏_Win11全屏显示设置【美化】  Win10怎样设置闹钟贪睡时间 Win10闹钟贪睡时长设置【步骤】  mac怎么打开终端_MAC终端Terminal使用入门与常用命令【教程】  Windows10任务栏图标变成白色文件_Win10重建图标缓存修复方法  C++如何使用std::async进行异步编程?(future用法)  Win11怎样安装微信开发者工具_Win11安装开发者工具教程【步骤】  Win11视频默认播放器怎么改_Win11关联第三方播放器【步骤】  Linux怎么修改用户密码_Linux系统passwd命令使用与权限管理【方法】  php删除数据怎么软删除_添加is_del字段标记删除【技巧】  Python函数参数高级用法_默认值与可变参数解析【教程】  如何在Golang中写入JSON文件_保存结构体数据到文件  Linux怎么实现内网穿透_Linux安装Frp客户端与服务端配置【方法】  XSLT怎么生成动态的HTML属性名和标签名  如何在Golang中捕获HTTP服务器错误_GolangHTTP Handler中error处理  如何使用Golang捕获测试日志_Golang testing日志记录方法  Win11怎么清理C盘下载文件夹_Win11清理下载文件夹技巧【教程】  Win11怎么设置虚拟内存_Windows 11优化内存性能提升速度【技巧】  Win11无法安装软件怎么办_Win11解除应用安装限制设置【修复】  如何在Golang中处理通道发送接收错误_防止阻塞或panic  Win11怎么关闭通知中心_Windows11系统通知与专注助手设置  Python文本编码与解码_跨平台解析说明【指导】 

 2025-12-08

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.