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

单例模式是一种常用的设计模式,有一些对象往往在全局中有且只需要一个,比如线程池,全局缓存,浏览器对象等,在JavaScript开发中使用也十分广泛,比如登录浮窗,不管我们点击多少次,这个浮窗应该只会创建一次,之后的创建应该是直接返回已创建好的浮窗模块,那么整个创建浮窗的逻辑就适合用单例模式来实现

下面我们先来用JavaScript实现一下类语言的简单单例模式

let singLeton = function (name) {this.name = name
}singLeton.instance = nullsingLeton.prototype.getName = function () {console.log(this.name)
}singLeton.getInstance = function (name) {if (!this.instance) {this.instance = new singLeton(name)}return this.instance
}let a = singLeton.getInstance('tom')
let b = singLeton.getInstance('jerry')console.log(a, b, a === b)

输出结果:

以上就是一个简单的单例模式的实现,但是这种单例模式意义并不大,正常创建一个单例应该是通过 new的方式创建,而不是需要使用者知道某个属性是单例模式的接口,下面我们再实现一种更为通用的单例模式

透明单例模式

let createDiv = (function (html) {let instance = nulllet CreateDiv = function (html) {if (instance) return instancethis.html = htmlthis.init()return instance = this}CreateDiv.prototype.init = function () {let div = document.createElement("div")div.innerHTML = this.htmldocument.body.appendChild(div)}return CreateDiv
})()let a = new createDiv('tom')
let b = new createDiv('jerry')console.log(a, b, a === b)

仔细观察这段代码,在内层的CreateDiv中其实做了很多事,1.创建对象和初始化init方法,2.保证只有一个实例对象。实际上这是违反“单一职责原则”的,也就是一个方法里只能执行一种功能,显然这样是不好的,假设我们每天要利用这个类,在页面中创建成千上百的div,这个时候我们就必须的改写CreateDiv构造函数,使其变成可以创建多个实例的类,而且还要把控制创建唯一对象的那段代码去掉,这样修改起来十分苦恼,我们可以使用代理的方式,抽离出控制创建唯一实例对象的那段代码,然后将CreateDiv改造成普通的创建div的类,得到如下代码

代理实现单例模式

let CreateDiv = function (html) {this.html = htmlthis.init()
}
CreateDiv.prototype.init = function () {let div = document.createElement("div")div.innerHTML = this.htmldocument.body.appendChild(div)
}// 引入代理类
const ProxySingletonCreateDiv = (function () {let instance = nullreturn function (html) {if (instance) return instancereturn instance = new CreateDiv(html)}
})()let a = new ProxySingletonCreateDiv('tom')
let b = new ProxySingletonCreateDiv('jerry')console.log(a, b, a === b)

不难看出,这样实现之后,不仅可以通过普通方式创建多个div,也可以通过代理类实现单例模式

以上就是类语言中实现方式,但是JavaScript严格意义上讲是一个无类的语言,在JavaScript中创建对象是十分简单的,既然我们只需要一个"唯一"的对象,为什么我们还要去创建一个创建对象的类呢? 这不就是脱裤子放屁多此一举嘛,所以以上的传统方式在JavaScript中不太适用。

同时,由于JavaScript中存在全局变量,所以在JavaScript中经常将全局变量当做单例来使用,虽然这种创建单例的方式是独一无二的,但是,很容易造成命名空间的污染,大型项目中,多个人协同开发,一不小心就会将你创建的单例给覆盖掉了,还得不断的加以限制,所以不建议使用全局变量的这种方式创建单例,可以使用命名空间来减少全局变量的使用,通过命名空间和闭包的结合,就可以实现无类的单例模式实现了,也就是上的几种代码(这里大家可能会觉得很奇怪,我明明说了上面的传统方式在JavaScript中不适用,为何在这又说就是以上代码的实现就是JavaScript中的单例模式,这里主要讲的其实是设计思路,与代码无关,由于JavaScript是无类的语言,所以无法写出类语言那种的形式,只是做了大概的模拟,本质上的代码实现还是JavaScript代码,仔细观察也不难看出,上面的代码就是用到了闭包创建私有变量的形式来保存构建好的单例的,也使用了原型链来模拟类中的静态方法,所以大家不必疑惑)

通用惰性单例

这种算是较为贴合实际情况的,将创建节点的逻辑抽离以及管理单例的逻辑也抽离出来,通过将创建节点的逻辑传入管理单例的构造函数中,从而实现单例模式,代码如下

let getSingle = function (fn) {let result = nullreturn function () {return result || (result = fn.apply(this, arguments))}
}let createLoginLayer = function () {let div = document.createElement('div')div.innerHTML = '我是登陆浮窗'div.style.display = 'none'document.body.appendChild(div)return div
}const loginLayer = getSingle(createLoginLayer)document.getElementById("loginButton").onclick = function () {let loginLayerAsc = loginLayer()loginLayerAsc.style.display = 'block'
}

大家不妨试试最后的结果,我们根据上面的代码在来实现动态第三方页面的加载

let getSingle = function (fn) {let result = nullreturn function () {return result || (result = fn.apply(this, arguments))}
}let createSingleIframe = getSingle(function () {let iframe = document.createElement('iframe')document.body.appendChild(iframe)return iframe
})document.getElementById("loginButton").onclick = function () {let loginLayerAsc = createSingleIframe()loginLayerAsc.src = 'https://www.baidu.com/'
}

最终结果很意外,被拦截拒绝了,哈哈哈,不过说明单例的实现是成功的,不管点击多少次登录,都有且仅会创建一次模块

以上就是关于单例模式的所有的介绍,包含了许多闭包,需要对闭包理解透彻之后才能完全读懂单例模式的代码

内容摘自《JavaScript设计模式与开发实践》· 曾探 · 著

JavaScript设计模式之“单例模式“相关推荐

  1. Javascript设计模式之单例模式

    前言:菜鸡也有梦想,而我的梦想就是进一个真正的互联网大厂.以前学习的时候没有系统的整理,从今天开始要保持每周写博客的习惯,希望自己可以有所成长.为了培养编程思维,决定从设计模式开始写起.我是通过读&l ...

  2. javascript 设计模式之单例模式

    单例模式是一种简单而非常实用的模式特别是惰性单例技术,下面例子贴出了单列模式的代码 <button id="loginBtn">登录</button>< ...

  3. javaScript设计模式---(单例模式学习)

    单例模式 一个类只能有一个实例化对象.如页面中的弹出框蒙层,一个页面只需要一个. 实现方式:创建一个类,这个类包含一个方法,这个方法在没有对象存在的情况下,将会创建一个新的实例对象.如果对象存在,这个 ...

  4. JavaScript设计模式——单例模式的理解与应用

    JavaScript设计模式--对单例模式的一些见解 JavaScript设计模式主要分类: ①创建型设计模式,例如单例模式.工厂模式 ②结构型设计模式,例如装饰者模式.适配器模式 ③行为型设计模式, ...

  5. JavaScript设计模式之创建型设计模式

    此系列总结与<JavaScript设计模式>,总共分为创建型设计模式.结构型设计模式.行为型设计模式.技巧型设计模式和架构性设计模式五大类. github原文地址:YOU-SHOULD-K ...

  6. JavaScript 设计模式核⼼原理与应⽤实践之单例模式——Vuex的数据管理哲学

    JavaScript 设计模式核⼼原理与应⽤实践之单例模式--Vuex的数据管理哲学 保证一个类仅有一个实例,并提供一个访问它的全局访问点,这样的模式就叫做单例模式. 单例模式的实现思路 思考这样一个 ...

  7. JavaScript设计模式与开发实践系列之单例模式

    本系列为<JavaScript设计模式与开发实践>(作者:曾探)学习总结,如想深入了解,请支持作者原版 单例模式 实现单例模式 单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的 ...

  8. JavaScript设计模式与开发实践 - 单例模式

    引言 本文摘自<JavaScript设计模式与开发实践> 在传统开发工程师眼里,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返 ...

  9. JavaScript设计模式----单例模式

    声明:这个系列为阅读<JavaScript设计模式与开发实践> --曾探@著一书的读书笔记 1.单例模式的特点和定义 保证一个类仅有一个实例,并且提供一个访问它的全局访问点. 2.传统面向 ...

  10. 16种JavaScript设计模式(中)

    简介 上文中介绍了学习设计模式前需要了解的一些基础概念和js的基础模式-原型模式,没看过的同学可以点这里,本章将介绍以下几种模式 单例模式 策略模式 代理模式 迭代器模式 发布订阅模式 命令模式 组合 ...

最新文章

  1. 计算机基本水平测试内容,浙江师范大学计算机基础水平测试大纲(2018级新生使用)...
  2. 分子生物学-共价键基础
  3. 百度Create大会:百度AI安全研究的进展与愿景
  4. mysql内部实现原理面试_理解完这些基本上能解决面试中MySql的事务问题
  5. 应用实时监控 ARMS 上线用户行为回溯功能
  6. 两点(51Nod-1416)
  7. 确定比赛名次(HDU-1285)
  8. easyui修改css样式,修改easyui的easyloader的默认css目录路径
  9. 微软源代码遭 SolarWinds 黑客访问
  10. 强连通分量算法(2)
  11. 脚本——web_custom_request函数详解
  12. 时间序列深度学习:状态 LSTM 模型预测太阳黑子(上)
  13. UE4+LiveLinkFace面部动作捕捉
  14. 拼音表大全图_20x11二层带阁楼别墅设计图纸及效果图大全
  15. Undo log日志详解
  16. 关于计算机ps读后感,ps心得体会4篇
  17. WEB应用之JSP+Servlet
  18. Second《C++ Primer》中文第四版
  19. Android studio连接(逍遥)模拟器
  20. 【hangs】impdp hangs

热门文章

  1. android多开原理和检测。
  2. JavaScript 技术篇-如何实现在线logo网站制作后的logo去水印,免费制作无水印logo方法
  3. 神经网络(单层感知器)
  4. 第3章:混仿高级特性
  5. Python使用 opencv对CT图进行医学处理
  6. 网盘搜索引擎(持续更新中)
  7. VSE++: Improving Visual-Semantic Embeddings with Hard Negatives------BMVC 2018
  8. node.js + busboy 多文件上传
  9. matlab批量裁剪图像并保存,matlab批量裁剪tif图片
  10. C#单位档案信息管理系统源码