首页 > 编程语言 >JavaScript设计模式及代码实现——单例模式

JavaScript设计模式及代码实现——单例模式

时间:2022-08-29 13:56:18浏览次数:45  
标签:const JavaScript instance 实例 单例 new 设计模式 getSingletonOfA

单例模式

singleton

1 定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2 应用时机

  1. 当一个类的实例被频繁使用,如果重复创建这个实例,会无端消耗资源。比如 dialog 弹窗会被全局重复使用
  2. 业务功能本身决定了全局只能有唯一的实例。比如 redux 管理的数据,只能有唯一的一份

3 应用场景

  1. 对于前端应用的许多基本组件:比如 dialog、message等等,会被全局频繁使用,就应该维护一个全局唯一的实例,避免重复创建带来不必要的资源消耗。业务组件也同理:比如购物车组件、登录弹窗组件等
  2. 对于一些通用的工具库,经常会使用单例模式。比如我们通常会创建一个全局唯一的 axios 实例来发起网络请求
  3. 对于 redux、vuex 等状态管理库,都采用全局唯一的 store 来存储应用状态数据

等等 ……

4 代码实现

4.1 全局变量和命名空间

根据单例模式的定义

// 维护类 A 的唯一实例
class A {}
window.a = new A(); // 或 global.a = new A(); 浏览器用 window

这种方法存在很明显的缺陷,因为同一项目的所有程序员都可以定义全局的变量 a,很容易造成全局污染。

解决办法是设定一个自己的命名空间来和其他人区分

// 比如我设定自己的命名空间 JiMing
window.JiMing = {
	a: new A()
}

如果使用 TypeScript ,可以使用关键字 namespace

namespace JiMing {
  export const a = new A();
}

4.2 惰性单例

上述实现中,我们直接在全局创建了类 A 的单一实例,无论其是否被使用,这在某些场景会造成资源浪费。有时我们希望在用到的时候再创建实例

如下代码利用立即执行函数和闭包来得到 A 的单例获取函数:getSingletonOfA

class A {}
const getSingletonOfA = (() => {
  let instance;
  return () => {
    return (instance ??= new A());
  };
})();

只有在调用getSingletonOfA才会创建 A 的实例,并且会在闭包中将其储存在 instance 中,重复调用getSingletonOfA会获取相同的实例

const a1 = getSingletonOfA();
const a2 = getSingletonOfA();
console.log(a1 === a2); // true

上述方法能够满足单例模式,但是不够通用,改造如下

const createSingletonUtil = (className) => {
  let instance;
  return () => {
    return (instance ??= new className());
  };
};

我们封装一个工具函数createSingletonUtil,调用该函数后可以获得任意类的“单例获取函数”

const getSingletonOfA = createSingletonUtil(A);
const a3 = getSingletonOfA();
const a4 = getSingletonOfA();
console.log(a3 === a4); // true

createSingletonUtil 的 TypeScript 实现如下:

class A {}
const createSingletonUtil = <T>(className: new () => T) => {
  let instance: T;
  return () => {
    return (instance ??= new className());
  };
};

const getSingletonOfA = createSingletonUtil<A>(A);
const a1 = getSingletonOfA();
const a2 = getSingletonOfA();
console.log(a1 === a2);

当然惰性单例也有缺点,对于某些类,如果创建实例需要较长时间,这时在用到的时候再创建恐怕来不及,可能会产生其他副作用,比如造成页面卡顿。在此场景下,在应用初始化时就创建其实例或许会有更好的用户体验

上述两种方法根据不同的业务场景择一使用即可

公众号【今天也要写bug】(op-bot)提问答疑

标签:const,JavaScript,instance,实例,单例,new,设计模式,getSingletonOfA
From: https://www.cnblogs.com/bidong/p/16635694.html

相关文章

  • 设计模式—模板方法模式(template)
         模板方法模式,我们来看一下定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。我们来定......
  • 设计模式-装饰者模式(Decorate)
    首先我们来看一下装饰者模式的UML图 图中各个类的含义不懂没有关系,下面我会用一个形象的例子来一一介绍他们,相信大家看完后肯定就明白了  比如,我们玩了一款游戏,里......
  • 设计模式之(3)——抽象工厂方法模式
    定义:抽象工厂模式简单地讲,就是提供一个超级工厂,围绕这个超级工厂创建其他工厂;抽象工厂模式提供一个创建一些列相关或者相互依赖对象的接口;在此之前我们先来讲一下产品......
  • 了解异步 JavaScript
    了解异步JavaScriptphotofromunsplash介绍我发现异步JavaScript是大多数初学者最容易混淆的概念之一。我也不容易掌握。虽然我看了很多教程,也阅读了很多关于它的......
  • 为什么在Javascript中声明之前可以访问变量?
    为什么在Javascript中声明之前可以访问变量?毫无疑问,当今最常用和最著名的语言之一是JavaScript,如今它无处不在,我们可以创建Web应用程序和系统,在后端开发API并创建移......
  • 学习设计模式和画图
    目录参考参考使用keynote画图https://www.yrunz.com/p/用keynote画出手绘风格的配图/使用plantuml进行设计......
  • JavaScript--关于this
    一、为什么会有this的出现  “this关键词是JS中最复杂的机制之一,它是一个很特别的关键字,被自动定义在所有函数的作用域中”根据凯尔辛普森的书中描述,刚开始阅读时我对......
  • leetcode 斐波那契数列 javascript实现
    写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项(即F(N))。斐波那契数列的定义如下:F(0)=0,  F(1) =1F(N)=F(N-1)+F(N-2),其中N>1.斐波那契数列由0......
  • JavaScript的函数
    //alert是JavaScript语言提供的一个警告函数//它可以接收任意类型的参数,这个参数就是警告框的提示信息   <!DOCTYPEhtml><htmllang="en"><head><metacharse......
  • 9.设计模式-原型模式
    1.单例模式1.饿汉式packagecom.serlyf.singleton;/***单例模式-饿汉式*1.构造私有*2.本类创建静态示例*3.getInstance()方法公开*/publicclassSingl......