JavaScript编程的单例设计模讲解

JavaScript编程的单例设计模式讲解

在JavaScript开发中,单例模式是一个常见的设计模式。它可以保证一个类只有一个实例,并提供一个全局可访问该实例的访问点。

使用场景

当一个对象需要在整个应用程序中只有一个实例时,就可以考虑使用单例模式。如:

  1. 全局状态管理
  2. 路由管理
  3. 模态框管理
  4. 数据库连接池
  5. WebSocket连接管理等。

基本实现方式

let singleton = (function(){
  let instance;

  function init() {    
    // 私有方法和私有属性
    let privateVar = 'I am private';
    function privateMethod() {
      console.log('This is private method');
    }

    // 公有方法和属性
    return {
      publicMethod: function() {
        console.log('This is public method');
      },
      publicVar: 'I am public',

      // 获取实例
      getInstance: function() {
        if (!instance) {
          instance = init();
        }
        return instance;
      }
    }
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  }
})();

let s1 = singleton.getInstance();
let s2 = singleton.getInstance();
console.log(s1 === s2); // true

以上代码使用了闭包和IIFE的特性,使得init函数只会执行一次并返回全局唯一的单例对象。

示例说明

示例1:全局状态管理

假设我们需要实现一个全局唯一的状态管理器,并且需要实现以下功能:

  1. getState方法获取当前状态
  2. setState方法设置当前状态
  3. subscribe方法订阅状态变更事件
  4. notify方法通知所有订阅者状态变更事件

基于上述需求,我们可以使用单例模式实现一个状态管理器:

let stateManager = (function(){
  let instance;

  function init() {    
    let state = 0;
    let subscribers = [];

    function notifySubscribers() {
      for(let i=0; i<subscribers.length; i++) {
        subscribers[i]();
      }
    }

    return {
      getState: function() {
        return state;
      },
      setState: function(s) {
        state = s;
        notifySubscribers();
      },
      subscribe: function(fn) {
        subscribers.push(fn);
      },

      getInstance: function() {
        if (!instance) {
          instance = init();
        }
        return instance;
      }
    }
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  }
})();

// 调用
let sm1 = stateManager.getInstance();
let sm2 = stateManager.getInstance();
console.log(sm1 === sm2); // true

sm1.subscribe(() => console.log('状态变更了:' + sm1.getState()));
sm1.setState(1);
sm1.setState(2);

示例2:WebSocket连接管理

假设我们需要实现一个全局唯一的WebSocket连接管理器,并且需要实现以下功能:

  1. open方法打开一个WebSocket连接,并自动重连
  2. send方法向指定连接发送消息
  3. close方法关闭指定连接
  4. getAll方法获取所有连接状态

基于上述需求,我们可以使用单例模式实现一个WebSocket连接管理器:

let wsManager = (function(){
  let instance;

  function init() {
    let connections = [];

    function open(url) {
      let conn = new WebSocket(url);
      connections.push(conn);

      conn.addEventListener('open', () => {
        console.log('连接已建立:' + url);
      });

      conn.addEventListener('message', (e) => {
        console.log('收到消息:' + e.data);
      });

      conn.addEventListener('close', () => {
        console.log('连接已关闭:' + url);
        setTimeout(() => open(url), 1000);
      });

      return conn;
    }

    function close(conn) {
      conn.close();
      connections.splice(connections.indexOf(conn), 1);
      console.log('连接已关闭:' + conn.url);
    }

    function send(conn, message) {
      conn.send(message);
      console.log('向' + conn.url + '发送字符串消息:' + message);
    }

    function getAll() {
      let result = [];
      for (let i=0; i<connections.length; i++) {
        result.push({ url: connections[i].url, readyState: connections[i].readyState });
      }
      return result;
    }

    return {
      open: function(url) {
        return open(url);
      },
      close: function(conn) {
        return close(conn);
      },
      send: function(conn, message) {
        return send(conn, message);
      },
      getAll: function() {
        return getAll();
      },

      getInstance: function() {
        if (!instance) {
          instance = init();
        }
        return instance;
      }
    }
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  }
})();

// 调用
let ws = wsManager.getInstance().open('ws://localhost:8080/');
wsManager.getInstance().send(ws, 'hello');
wsManager.getInstance().close(ws);
console.log(wsManager.getInstance().getAll());

上述两个示例分别实现了全局状态管理和WebSocket连接管理的功能,并都应用了单例模式来保证全局唯一性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript编程的单例设计模讲解 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JavaScript 数组的进化与性能分析

    JavaScript 数组的进化与性能分析 简介 JavaScript 中的数组是一种常用的数据结构,用于存储一组有序的数据。在 JavaScript 数组的进化过程中,出现了多种不同的实现方式,每种实现方式都有其优缺点。本文将简要介绍 JavaScript 数组的进化历程,并根据不同实现方式对其性能进行分析和比较。 传统数组实现 最早的 JavaScrip…

    JavaScript 2023年5月27日
    00
  • JavaScript执行顺序详细介绍

    下面是JavaScript执行顺序的详细介绍攻略。 1. 什么是执行顺序 在JavaScript中,执行顺序指的是代码在运行时所遵循的顺序,即JavaScript引擎根据代码的语法和逻辑来决定执行哪个代码块。对于同步执行的代码,执行顺序遵循“自上而下,从左到右”的顺序,而对于异步执行的代码,则需要遵循事件循环机制的规则。 2. 同步执行代码的执行顺序 对于同…

    JavaScript 2023年5月18日
    00
  • 微信小程序 时间格式化(util.formatTime(new Date))详解

    为了实现微信小程序的时间格式化,我们可以使用util.formatTime()函数。这个函数将一个Date对象转换为对应的字符串形式,具体格式化方式由传入的参数进行控制。 以下是“微信小程序 时间格式化(util.formatTime(new Date))详解”攻略的详细实现过程: 1. 引入util模块 在微信小程序中使用util模块需要先引入该模块,使用…

    JavaScript 2023年5月27日
    00
  • fastclick插件导致日期(input[type=”date”])控件无法被触发该如何解决

    首先,需要梳理一下问题的背景和现象: 背景:当网页中使用了fastclick插件时 现象:用户在点击日期选择控件时,控件无法弹出日期选择框,无法选择日期。 这是因为fastclick插件会阻止浏览器默认的双击事件(有些日期选择控件在点击两次时才能弹出)和移动端的300ms延迟,从而提升点击体验。然而这个插件的实现方式是,将点击事件改为tap事件,从而可能会对…

    JavaScript 2023年6月11日
    00
  • 千篇一律的JS运算符讲解,一起来看看

    千篇一律的JS运算符讲解,一起来看看 前言 JS运算符是编写JS代码时非常基本的一种语法。很多初学者在学习JS时可能会忽略这些运算符的学习,但却是非常重要的基础。在本篇文章中,我们将会全面讲解JS的运算符,并提供一些示例来帮助读者更好地理解这些内容。 算术运算符 运算符 描述 示例 + 加法 10 + 20 = 30 – 减法 20 – 10 = 10 * …

    JavaScript 2023年5月28日
    00
  • jdk1.8+vue elementui实现多级菜单功能

    下面我将详细讲解“jdk1.8+vue elementui 实现多级菜单功能”的攻略。 一、准备工作 首先需要安装jdk1.8及以上版本和vue-cli的脚手架工具,具体可以参考相关官方文档。 然后需要在vue项目中安装element-ui组件库,可以使用npm命令进行安装,示例代码如下: npm install element-ui –save 在mai…

    JavaScript 2023年6月10日
    00
  • JS实现Cookie读、写、删除操作工具类示例

    下面就是详细讲解“JS实现Cookie读、写、删除操作工具类示例”的完整攻略。 什么是Cookie? 先来简单介绍一下什么是Cookie。Cookie是一种在客户端(浏览器)存储数据的技术,用于存储各种信息,如登录状态、用户个性化设置、购物车商品等。Cookie的使用可以在服务器端通过响应头设置Cookie,在客户端通过document.cookie读取和修…

    JavaScript 2023年6月10日
    00
  • 详解vue-router导航守卫

    下面就详细讲解下“详解vue-router导航守卫”的完整攻略。 什么是vue-router导航守卫? vue-router导航守卫分为全局守卫和路由独享守卫,可以在导航过程中拦截和控制,用来控制页面跳转、权限校验等操作。可以通过导航守卫来判断用户是否有权限访问某个页面,或者在某个页面离开时做数据清理等操作。 导航守卫一共包含三种类型:全局前置守卫、全局后置…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部