摘要:但是如何在对构造函数使用操作符创建多个对象的时候仅获取一个单例对象呢。单例的实例引用单例构造函数单例私有属性和方法暴露出来的对象改进之前在构造函数中重写自身会丢失所有在初始定义和重定义之间添加到其中的属性。
1. 单例模式
单例模式 (Singleton) 的实现在于保证一个特定类只有一个实例,第二次使用同一个类创建新对象的时候,应该得到与第一次创建对象完全相同的对象。
当创建一个新对象时,实际上没有其他对象与其类似,因为新对象已经是单例了 {a:1} === {a:1} // false 。
但是如何在对构造函数使用 new 操作符创建多个对象的时候仅获取一个单例对象呢。
2. 静态属性中的实例在构造函数的静态属性中缓存该实例,缺点在于 instance 属性是公开可访问的属性,在外部代码中可能会修改该属性。
function Universe() { if (typeof Universe.instance === "object") { // 判断是否已经有单例了 return Universe.instance } Universe.instance = this return this } var uni1 = new Universe() var uni2 = new Universe() uni1 === uni2 // true3. 闭包中的实例
可以把实例封装在闭包中,这样可以保证该实例的私有性并且保证该实例不会在构造函数之外被修改,代价是带来了额外的闭包开销。
function Universe() { var instance = this Universe = function() { // 重写构造函数 return instance } } var uni1 = new Universe() var uni2 = new Universe() uni1 === uni2 // true
当第一次调用构造函数时,它正常返回 this ,然后在以后调用时,它将会执行重写构造函数,这个构造函数通过闭包访问了私有 instance 变量,并且简单的返回了该 instance。
4. 惰性单例有时候对于单例对象需要延迟创建,所以在单例中还存在一种延迟创建的形式,也有人称之为惰性创建。
const LazySingle = (function() { let _instance // 单例的实例引用 function Single() { // 单例构造函数 const desc = "单例" // 私有属性和方法 return { // 暴露出来的对象 publicMethod: function() {console.log(desc)}, publickProperty: "1.0" } } return function() { return _instance || (_instance = Single()) } })() console.log(LazySingle()===lazySingle()) // true console.log(LazySingle().publickProperty) // 1.05. 改进
之前在构造函数中重写自身会丢失所有在初始定义和重定义之间添加到其中的属性。在这种情况下,任何添加到 Universe() 的原型中的对象都不会存在指向由原始实现所创建实例的活动链接:
function Universe() { var instance = this Universe = function() { return instance } } Universe.prototype.nothing = true var uni1 = new Universe() Universe.prototype.enthing = true var uni2 = new Universe() console.log(uni1 === uni2) // true uni1.nothing // true uni2.nothing // true uni1.enthing // undefined uni2.enthing // undefined uni1.constructor.name // "Universe" uni1.constructor === Universe // false
之所以 uni1.constructor 不再与 Universe() 相同,是因为uni1.constructor仍然指向原始的构造函数,而不是重定义之后的那个构造函数。
可以通过一些调整实现原型和构造函数指针按照预期的那样运行:
function Universe() { var instance Universe = function Universe() { return instance } Universe.prototype = this // 保留原型属性 instance = new Universe() instance.constructor = Universe // 重置构造函数指针 instance.start_time = 0 // 一些属性 instance.big = "yeah" return instance } Universe.prototype.nothing = true var uni1 = new Universe() Universe.prototype.enthing = true var uni2 = new Universe() console.log(uni1 === uni2) // true uni1.nothing & uni2.nothing & uni1.enthing & uni2.enthing // true uni1.constructor.name // "Universe" uni1.constructor === Universe // true uni1.big // "yeah" uni2.big // "yeah"
本文是系列文章,可以相互参考印证,共同进步~
JS 抽象工厂模式
JS 工厂模式
JS 建造者模式
JS 原型模式
JS 单例模式
JS 回调模式
JS 外观模式
JS 适配器模式
JS 利用高阶函数实现函数缓存(备忘模式)
JS 状态模式
JS 桥接模式
JS 观察者模式
网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出~
参考:
《JavaScript模式》 P143
《Javascript 设计模式》 - 张荣铭
设计模式之单例模式
PS:欢迎大家关注我的公众号【前端下午茶】,一起加油吧~
另外可以加入「前端下午茶交流群」微信群,长按识别下面二维码即可加我好友,备注加群,我拉你入群~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/92144.html
摘要:文章系列设计模式单例模式设计模式策略模式设计模式代理模式概念单例模式的定义是保证一个类仅有一个实例,并提供一个访问它的全局访问点。在开发中,单例模式的用途同样非常广泛。 前言 本系列文章主要根据《JavaScript设计模式与开发实践》整理而来,其中会加入了一些自己的思考。希望对大家有所帮助。 文章系列 js设计模式--单例模式 js设计模式--策略模式 js设计模式--代理模式 概念...
摘要:什么是设计模式设计模式是一种能够被反复使用,符合面向对象特性的代码设计经验的总结,合理的使用设计模式能够让你得代码更容易维护和可靠设计模式的类型共分为创建型模式,结构型模式,行为型模式三种创建型模式创建型模式是对一个类的实例化过程进行了抽象 什么是设计模式 设计模式是一种能够被反复使用,符合面向对象特性的代码设计经验的总结,合理的使用设计模式能够让你得代码更容易维护和可靠设计模式的类型...
摘要:什么是单例模式单例模式是一种十分常用但却相对而言比较简单的单例模式。对象就是单例模式的体现。总结单例模式虽然简单,但是在项目中的应用场景却是相当多的,单例模式的核心是确保只有一个实例,并提供全局访问。 1. 什么是单例模式? 单例模式是一种十分常用但却相对而言比较简单的单例模式。它是指在一个类只能有一个实例,即使多次实例化该类,也只返回第一次实例化后的实例对象。单例模式不仅能减少不必要...
阅读 2567·2023-04-25 17:33
阅读 647·2021-11-23 09:51
阅读 2950·2021-07-30 15:32
阅读 1394·2019-08-29 18:40
阅读 1939·2019-08-28 18:19
阅读 1464·2019-08-26 13:48
阅读 2236·2019-08-23 16:48
阅读 2274·2019-08-23 15:56