【Javascript】设计模式之单例模式

文章目录

  • 1、实现单例模式
  • 2、透明的单例模式
  • 3、用代理实现单例模式
  • 4、JavaScript 中的单例模式
  • 5、惰性单例
  • 6、通用的惰性单例
  • 7、小结

定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏
览器中的 window 对象等

1、实现单例模式

是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。
代码如下:

var Singleton = function (name) {this.name = name;this.instance = null;
};
Singleton.getInstance = function (name) {if (!this.instance) {this.instance = new Singleton(name);}return this.instance;
};var a = Singleton.getInstance('a');
var b = Singleton.getInstance('b');
console.log(a === b); // true

或者利用闭包:

var Singleton = function (name) {this.name = name;this.instance = null;
};
Singleton.getInstance = (function (name) {var instance = null;return function (name) {if (!instance) {instance = new Singleton(name);}return instance;};
})();var a = Singleton.getInstance('a');
var b = Singleton.getInstance('b');
console.log(a === b); // true

问题:
就是增加了这个类的“不透明性”,Singleton 类的使用者必须知道这是一个单例类

2、透明的单例模式

实现一个“透明”的单例类,用户从这个类中创建对象的时候,可以像使用其他任何普通类一样。

在下面的例子中,我们将使用 CreateDiv 单例类,它的作用是负责在页面中创建唯一的 div 节点,代码如下:

var CreateDiv = (function () {var instance = null;var CreateDiv = function (html) {if (instance) {return instance;}this.html = html;this.init();return (instance = this);};CreateDiv.prototype.init = function () {var div = document.createElement('div');div.innerHTML = this.html;document.body.appendChild(div);};return CreateDiv;
})();var a = new CreateDiv('a');
var b = new CreateDiv('b');console.log(a === b);

问题:
问题:假设我们某天需要利用这个类,在页面中创建千千万万的 div,即要让这个类从单例类变成一个普通的可产生多个实例的类,那我们必须得改写 CreateDiv 构造函数,把控制创建唯一对象的那一段去掉,这种修改会给我们带来不必要的烦恼

解决:
使用代理模式

3、用代理实现单例模式

在 CreateDiv 构造函数中,把负责管理单例的代码移除出去,使它成为一个普通的创建 div 的类:

var CreateDiv = function (html) {this.html = html;this.init();
};
CreateDiv.prototype.init = function () {var div = document.createElement('div');div.innerHTML = this.html;document.body.appendChild(div);
};// 引入代理类 proxySingletonCreateDiv:
var ProxySingletonCreateDiv = (function () {var instance;return function (html) {if (!instance) {instance = new CreateDiv(html);}return instance;};
})();var a = new ProxySingletonCreateDiv('a');
var b = new ProxySingletonCreateDiv('b');console.log(a === b);

跟之前不同的是,现在我们把负责管理单例的逻辑移到了代理类 proxySingletonCreateDiv 中。这样一来,CreateDiv 就变成了一个普通的类,它跟 proxySingletonCreateDiv 组合起来可以达到单例模式的效果

4、JavaScript 中的单例模式

在 JavaScript 开发中,我们经常会把全局变量当成单例来使用。
例如:

var a = {};

问题:
全局变量存在很多问题,它很容易造成命名空间污染

解决:
1、使用命名空间

var namespace1 = { a: function(){ alert (1); }, b: function(){ alert (2); } 
};

2、使用闭包封装私有变量

var user = (function(){ var __name = 'sven', __age = 29; return { getUserInfo: function(){ return __name + '-' + __age; } } 
})();

5、惰性单例

惰性单例指的是在需要的时候才创建对象实例
例子:

var createLoginLayer = (function () {var div;return function () {if (!div) {div = document.createElement('div');div.innerHTML = '我是浮窗';document.body.appendChild(div);}return div;}
})()// 用户点击按钮的时候才开始创建该浮窗
document.getElementById('loginBtn').onclick = function () {var loginLayer = createLoginLayer();
};

问题:违反单一职责原则,创建对象和管理单例的逻辑都放在 createLoginLayer对象内部,如果我们下次需要创建页面中唯一的 iframe,或者 script 标签,用来跨域请求数据,就
必须得如法炮制,把 createLoginLayer 函数几乎照抄一遍
解决:第6点

6、通用的惰性单例

将单例的逻辑从原来的代码中抽离出来,这些逻辑被封装在 getSingle函数内部,创建对象的方法 fn 被当成参数动态传入 getSingle 函数

var getSingle = function (fn) {var result;return function () {return result || (result = fn.apply(this, arguments));}
}

使用示例:

var createLoginLayer = function () {var div = document.createElement('div');div.innerHTML = '我是浮窗';document.body.appendChild(div);return div;
}
var createSingleLoginLayer = getSingle(createLoginLayer);document.getElementById('loginBtn').onclick = function () {var loginLayer = createSingleLoginLayer();
};

也可以用在只执行一次的函数
比如:给一个div绑定事件

var bindEvent = getSingle(function () {console.log('给div绑定事件~');return true;
});bindEvent();
bindEvent();
bindEvent();

7、小结

单例模式是一种简单但非常实用的模式,特别是惰性单例技术,在合适的时候才创建对象,并且只创建唯一的一个。更奇妙的是,创建对象和管理单例的职责被分布在两个不同的方法中,这两个方法组合起来才具有单例模式的威力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/716648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript 学习总结(16)—— 实用小函数总结

1.匹配正整数 // 匹配正整数 let isPositiveNum = val => {return /^[1-9]d*$/.test(val); }; console.log(isPositiveNum(9)) //true console.log(isPositiveNum(2.2)) //false 2.匹配负整数 // 匹配负整数let isNegativeNum = val => {return /^-[1-9]d*$/.test(val…

R750 install AMD MI210GPU

一、 查看服务器GPU卡信息 可以首先在服务器上check 当前GPU的详细信息是否匹配 二、安装 Ubuntu22.04操作系统 服务器CHECK 安装的AMD GPU 是否被系统识别 #lspci | grep AMD 查看GPU信息 可以看到已经识别成功 三、安装AMD GPU驱动 https://rocm.docs.amd.com/projec…

linux 根目录下结构

/ 虚拟目录的根的目录,通常不会在这里放置文件 /bin:存放频繁使用的命令,二进制文件,存放了很多用户级的GNU实用工具。 /boot:引导目录,存放引导文件,包含启动Linux所需的核心文件。 /dev:设…

智能驾驶规划控制理论学习05-车辆运动学规划案例分析

目录 案例一——Hybrid A*(基于正向运动学) 1、基本思想 2、 实现流程 3、启发函数设计 4、分析扩张(Analytic Expansions) 5、分级规划(Hierarchical planning) 案例二——State Lattice Planning&…

子矩阵的和 刷题笔记 {二维前缀和}

首先我们的目标是让 s[i][j]表示为其左方和上方形成的矩阵所有元素的和 加上s[i-1][j]和s[i][j-1]后 s[i-1][j-1]部分重复了所以减去 最后加上a[i][j]即可完成目标 s[i][j]s[i-1][j]s[i][j-1]-s[i-1][j-1]a[i][j]; 然后看题目要求 要求x1,y1,x2,y2围成的小正方形内的元素和…

C/C++工程师面试题(数据库篇)

索引的优缺点 索引是一种支持快速查找特定行的数据结构,如果没有索引,就需要遍历整个表进行查找。用于提高数据检索的速度和效率。 好处: 提高检索速度: 索引可以加快数据的检索速度,因为它们允许数据库系统直接定位到…

Revit-二开之立面视图创建FilledRegion-(3)

在上一篇博客中介绍了FilledRegion的创建方法,这种方法通常只在平面视图中适用,在三维视图中也是无法创建的(目前研究的是这样的,如果有其他方法,请赐教)。 本片文章介绍一个下在立面视图中创建FilledRegion的方法,主要操作是在立面视图中拾取一个点,然后以该点为原点,…

YOLOv5 项目:推理代码和参数详细介绍(detect)

1、前言 本章将介绍yolov5项目的推理函数,关于yolov5的下载和配置环境,参考上一篇文章: YOLOv5 项目:环境配置-CSDN博客 pycharm 中打开的推理模块如红框中所示 pycharm将conda新建的虚拟环境导入,参考 :…

快速模幂(c++题解)

题目描述 试求ab%n的值,其中a、b、n均为整数范围内的数。 输入格式 三个整数即a、b、n。 输出格式 输出结果。 样例 样例输入 复制1 1 1样例输出 复制0 _____________________________________________________________________________ ok呀总算学到一个…

从 AI 的爆火聊聊用户界面(UI)的演进

目录 用户界面的起源与发展 用户界面的设计原则与趋势 用户界面未来的方向 小结 用户界面(User Interface,简称 UI)是人与计算机系统交互的媒介,用户可以通过用户界面向计算机发送指令,同时计算机可以通过用户界面…

面试 Java 基础八股文十问十答第十五期

面试 Java 基础八股文十问十答第十五期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新! ⭐点赞⭐收藏⭐不迷路!⭐ 1)BIO, NIO, AIO 有什么…

简单实现Transformer的自注意力

简单实现Transformer的自注意力 关注{晓理紫|小李子},获取技术推送信息,如感兴趣,请转发给有需要的同学,谢谢支持!! 如果你感觉对你有所帮助,请关注我。 源码获取:VX关注并回复chatg…

二叉树的右视图,力扣

目录 题目: 我们直接看题解吧: 快速理解解题思路小建议: 审题目事例提示: 解题方法: 解题分析: 解题思路: 代码实现(DFS): 代码1: 补充说明: 代码2&#xff1…

Vue.js中的$nextTick

其实目前在我现有的开发经历中,我还没有实际运用过$nextTick,今天在看书时,学习到了这个东西,所以做个笔记记录一下。 一、$nextTick是什么? $nextTick 是 Vue提供的一个方法,用于在 DOM 更新之后执行回调…

AI:148-开发一种智能语音助手,能够理解和执行复杂任务

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

浅谈钩子方法

何为钩子方法 钩子方法(Hook methods)是一种在面向对象编程中常用的设计模式,也被称为模板方法模式。在这种模式中,父类定义了一个算法的框架,并且将一些步骤的实现延迟到子类中。子类可以通过重写这些“钩子方法”来改…

[技巧]Arcgis之图斑四至点批量计算

前言 上一篇介绍了arcgis之图斑四至范围计算,这里介绍的图斑四至点的计算及获取,两者之间还是有差异的。 [技巧]Arcgis之图斑四至范围计算 这里说的四至点指的是图斑最东、最西、最南、最北的四个地理位置点坐标,如下图: 四至点…

青山隐隐,败叶萧萧

给定序列需满足二个条件:本身是质数,相邻二项之和仍为质数 首先一个偶数2*n不能通过2*k(k取整数)得到质数。 奇数2*n-12*k2*(nk)-1,可能得到质数 那么若序列中存在偶数,一定不满足第一个条件(特判0,2&am…

STM32进阶笔记——复位、时钟与滴答定时器

本专栏争取每周三更新直到更新完成,期待大家的订阅关注,欢迎互相学习交流。 目录 一、复位1.1 软件复位1.2 低功耗管理复位 二、时钟2.1 系统时钟(SYSCLK)选择2.2 系统时钟初始化 三、滴答定时器(Systick)3.1 SysTick部分寄存器3.…

部署bpmn项目实现activiti流程图的在线绘制

本教程基于centos7.6环境中完成 github开源项目: https://github.com/Yiuman/bpmn-vue-activiti软件:git、docker 1. 下载源代码 git clone https://github.com/Yiuman/bpmn-vue-activiti.git2. 修改Dockerfile文件 声明基础镜像,将项目打包&#xff…