news 2026/7/22 18:19:49

JavaScript设计模式(一):单例模式实现与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript设计模式(一):单例模式实现与应用

先提出一个问题,为什么要学习设计模式

难道是提出一个代码形容词,是为了让代码看起高大上 or 装逼

先看下设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案

我的个人理解就是,设计模式是前人对于解决问题提炼出来的一种思想,其实我们日常代码中就会用到一些设计模式。

像我们平时用的装饰器可以看作是装饰者模式,ES6 提供的proxy也可以看作是代理模式,像 JavaScript 中的自定义事件 +addEventListener就采用的是发布订阅模式

设计模式是为了让你的代码变得简单而优雅。有很高的可重用性可维护性以及可扩展性

设计模式有很多种,我们今天先来盘一下最常用和经典的设计模式之一:单例模式

1、单例模式定义

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点

其实就是,第一次访问会进行初始化,创建一个实例,后面访问的时候拿到的都是这个实例,不会再重新创建

classSingleton{constructor(name){this.name=name;}getName(){returnthis.name;}staticgetInstance(name){returnthis.instance||(this.instance=newSingleton(name))}}constinstance1=Singleton.getInstance('zs')constinstance2=Singleton.getInstance('lisi')console.log(instance1===instance2)// true

在单例类Singleton上定义一个获取实例的getInstance方法,第一次调用getInstance的时候创建一个Singleton实例保存在instance属性上,后面再获取就直接取this.instance

但是这样会出现一个问题,用户如果不调用getInstance,而直接去new Singleton,这样还是会创建多个实例出来,这样不是我们所期望的。

2、优化版

我们定义一个Singleton类,并用一个instance变量来保证在new 多次时,全局Singleton类实例的唯一性。

letinstance=null;classSingleton{constructor(name){this.name=name;if(!instance){instance=this;}returninstance;}}constinstance1=newSingleton('zs')constinstance2=newSingleton('lisi')console.log(instance1===instance2)// true

3、更优雅的实现:使用代理模式实现单例

其实我们可以用ES6的proxy来实现单例,其代码如下:

classPerson{constructor(name,age){this.name=name;this.age=age;}}functionsingleton(className){letinstance=null;returnnewProxy(className,{construct(target,args){if(!instance){instance=Reflect.construct(target,args);}returninstance;}})}constProxyPerson=singleton(Person);constperson1=newProxyPerson();constperson2=newProxyPerson();console.log(person1===person2);// true

4、代理模式实现单例的好处

  1. 解耦和单一职责原则:我们使用了代理之后,等于在我们使用的客户端和实际对象两者中间,加入了一层代理对象,而代理对象相当于一个黑盒子,而对我我们客户端来说,使用的时候不关心他里面的逻辑和实现细节,只关心它给我们提供了哪些功能和接口,调用就完事了, 这样遵循了单一职责原则,提高了代码的可维护性。
  2. 控制访问和延迟加载:其实也可以说就是安全性,在代理层做校验可以说是再好不过了,可以先把一些错误情况给拦截掉,起到访问控制的效果,然后也可以根据情况,决定时候延迟创建实例,也就是我们说的惰性单例,这样对于CPU密集型的实例来说,同时也能大大提高性能
  3. 扩展性:我们可以在代理层通过继承或实现相同的接口来扩展实际对象的功能,这样就可以做到不修改实际对象的源码,又增加上了扩展功能。

5、单例模式的应用

假如我们要创建一个全局唯一的弹框,我们很容易先写在创建弹框的代码:

constdiv=document.createElement('div')div.innerHTML='我是全局唯一的弹框'div.style.display='none'document.body.appendChild(div)

创建弹框我们有两种思路,我们可以在一开始渲染页面的时候就创建这个弹框,然后通过控制display进行显示隐藏,当然也可以惰性的懒加载,第一次用到的时候再去创建弹框,为了性能考虑,我们当然是选择后者。

<html><body><buttonid="btn">显示弹框</button></body><script>constgetSingle=(fn)=>{letinstance=nullreturn(...args)=>{returninstance||(instance=fn.apply(this,args))}}constcreateModel=()=>{constdiv=document.createElement('div')div.innerHTML='我是全局唯一的弹框'div.style.display='none'document.body.appendChild(div)returndiv;}constcreateSingleModel=getSingle(createModel);btn.addEventListener('click',()=>{constmodel=createSingleModel();model.style.display='block';})</script></html>

我们先把创建弹框的逻辑抽离到createModel方法中,然后我们创建一个管理单例的方法getSingle,先调用getSingle,将createModel交给getSingle去管理,这样就实现了唯一性,然后在按钮点击的时候,在调用getSingle返回的方法就行啦。

小结

上面介绍Javascript最经典的设计模式之一单例模式,简单来说,单例就是单实例,就是全局只能被创建一次,我们还用了代理对象来实现单例,用以增加其维护性扩展性

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 18:19:49

告别Matplotlib白边烦恼:plt.savefig实战技巧与常见问题排查

告别Matplotlib白边烦恼&#xff1a;plt.savefig实战技巧与常见问题排查 在数据可视化工作中&#xff0c;Matplotlib作为Python生态中最经典的绘图库&#xff0c;几乎成为每个数据分析师的标配工具。但许多初学者在将精心制作的图表保存为图片时&#xff0c;常常会遇到一个令人…

作者头像 李华
网站建设 2026/7/14 14:16:20

免费在线P2P文件传输网站

地址&#xff1a;https://filetsf.online/ 极简主义风格&#xff0c;只保留最基本文件传输功能 P2P 文件传输&#xff0c;安全高效&#xff0c;打洞成功速度加倍 所见即所得&#xff0c;免费好用 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a;

作者头像 李华
网站建设 2026/7/14 14:16:22

SPSS岭回归实战:从语法调用到结果解读全流程解析

1. 什么是岭回归&#xff1f;为什么需要它&#xff1f; 当你用普通最小二乘法做线性回归时&#xff0c;如果自变量之间存在高度相关性&#xff08;专业术语叫"多重共线性"&#xff09;&#xff0c;就会遇到一个头疼的问题&#xff1a;回归系数变得极不稳定&#xff…

作者头像 李华
网站建设 2026/7/14 14:16:22

欧姆龙NJ/NX PLC全ST程序案例分享:从框架到源码

欧姆龙NJ/NXPLC 全ST程序案例&#xff0c;全程序无加密&#xff0c;公司级框架&#xff0c;提供项目源码框架FB源码&#xff0c;触摸屏源码。 需要一定ST基础才能看懂。 重在分享编程思想 没用过该控制器的请慎用。 先安装1.2版本的环境 再升级到1.43 安装包里面的补丁一定要…

作者头像 李华
网站建设 2026/7/14 14:16:21

F746_GUI:面向STM32F7的轻量级嵌入式GUI库解析

1. F746_GUI嵌入式图形用户界面库深度解析F746_GUI是一个专为STMicroelectronics STM32F746NG Discovery开发板&#xff08;DISCO-F746NG&#xff09;定制的轻量级嵌入式GUI组件库。该库并非通用型UI框架&#xff0c;而是面向资源受限的Cortex-M7实时系统设计的、高度裁剪的控件…

作者头像 李华