深入理解JavaScript系列(25):设计模式之单例模式
介绍
从本章开始,我们会逐步介绍在JavaScript里使用的各种设计模式实现,在这里我不会过多地介绍模式本身的理论,而只会关注实现。OK,正式开始。
在传统开发工程师眼里,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
正文
在JavaScript里,实现单例的方式有很多种,其中最简单的一个方式是使用对象字面量的方法,其字面量里可以包含大量的属性和方法:
var mySingleton = { property1: "something", property2: "something else", method1: function () { console.log('hello world'); }};
如果以后要扩展该对象,你可以添加自己的私有成员和方法,然后使用闭包在其内部封装这些变量和函数声明。只暴露你想暴露的public成员和方法,样例代码如下:
var mySingleton = function () { /* 这里声明私有变量和方法 */ var privateVariable = 'something private'; function showPrivate() { console.log(privateVariable); } /* 公有变量和方法(可以访问私有变量和方法) */ return { publicMethod: function () { showPrivate(); }, publicVar: 'the public can see this!' };}; var single = mySingleton();single.publicMethod(); // 输出 'something private'console.log(single.publicVar); // 输出 'the public can see this!'
上面的代码很不错了,但如果我们想做到只有在使用的时候才初始化,那该如何做呢?为了节约资源的目的,我们可以另外一个构造函数里来初始化这些代码,如下:
var Singleton = (function () { var instantiated; function init() { /*这里定义单例代码*/ return { publicMethod: function () { console.log('hello world'); }, publicProperty: 'test' }; } return { getInstance: function () { if (!instantiated) { instantiated = init(); } return instantiated; } };})(); /*调用公有的方法来获取实例:*/Singleton.getInstance().publicMethod();
知道了单例如何实现了,但单例用在什么样的场景比较好呢?其实单例一般是用在系统间各种模式的通信协调上,下面的代码是一个单例的最佳实践:
var SingletonTester = (function () { //参数:传递给单例的一个参数集合 function Singleton(args) { //设置args变量为接收的参数或者为空(如果没有提供的话) var args = args || {}; //设置name参数 this.name = 'SingletonTester'; //设置pointX的值 this.pointX = args.pointX || 6; //从接收的参数里获取,或者设置为默认值 //设置pointY的值 this.pointY = args.pointY || 10; } //实例容器 var instance; var _static = { name: 'SingletonTester', //获取实例的方法 //返回Singleton的实例 getInstance: function (args) { if (instance === undefined) { instance = new Singleton(args); } return instance; } }; return _static;})(); var singletonTest = SingletonTester.getInstance({ pointX: 5 });console.log(singletonTest.pointX); // 输出 5
其它实现方式
方法1:
function Universe() { // 判断是否存在实例 if (typeof Universe.instance === 'object') { return Universe.instance; } // 其它内容 this.start_time = 0; this.bang = "Big"; // 缓存 Universe.instance = this; // 隐式返回this} // 测试var uni = new Universe();var uni2 = new Universe();console.log(uni === uni2); // true
方法2:
function Universe() { // 缓存的实例 var instance = this; // 其它内容 this.start_time = 0; this.bang = "Big"; // 重写构造函数 Universe = function () { return instance; };} // 测试var uni = new Universe();var uni2 = new Universe();uni.bang = "123";console.log(uni === uni2); // trueconsole.log(uni2.bang); // 123
方法3:
function Universe() { // 缓存实例 var instance; // 重新构造函数 Universe = function Universe() { return instance; }; // 后期处理原型属性 Universe.prototype = this; // 实例 instance = new Universe(); // 重设构造函数指针 instance.constructor = Universe; // 其它功能 instance.start_time = 0; instance.bang = "Big"; return instance;} // 测试var uni = new Universe();var uni2 = new Universe();console.log(uni === uni2); // true // 添加原型属性Universe.prototype.nothing = true; var uni = new Universe(); Universe.prototype.everything = true; var uni2 = new Universe(); console.log(uni.nothing); // trueconsole.log(uni2.nothing); // trueconsole.log(uni.everything); // trueconsole.log(uni2.everything); // trueconsole.log(uni.constructor === Universe); // true
方式4:
var Universe; (function () { var instance; Universe = function Universe() { if (instance) { return instance; } instance = this; // 其它内容 this.start_time = 0; this.bang = "Big"; };} ()); //测试代码var a = new Universe();var b = new Universe();alert(a === b); // truea.bang = "123";alert(b.bang); // 123
参考资料
https://github.com/shichuan/javascript-patterns/blob/master/design-patterns/singleton.html
http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript
深入理解JavaScript系列(25):设计模式之单例模式相关推荐
- 深入理解JavaScript系列(33):设计模式之策略模式(转)
介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很 ...
- 深入理解JavaScript系列(27):设计模式之建造者模式
介绍 在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一 ...
- 深入理解JavaScript系列(33):设计模式之策略模式
介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很 ...
- 深入理解JavaScript系列(32):设计模式之观察者模式
介绍 观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们 ...
- 深入理解JavaScript系列——汤姆大叔
原文地址 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaS ...
- 汤姆大叔深入理解JavaScript系列
深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...
- [转载]深入理解JavaScript系列 --汤姆大叔
深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...
- 深入理解JavaScript系列(转自汤姆大叔)
深入理解JavaScript系列(转自汤姆大叔) 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaSc ...
- 理解JavaScript中部分设计模式
理解JavaScript中部分设计模式 什么是设计模式 在软件工程中,设计模式是软件设计中常见问题可重用的方案.设计模式代表着经验丰富的软件开发人员使用的最佳实践.设计模式可以被认为是编程模板. 为什 ...
- 深入理解JavaScript系列:《你真懂JavaScript吗?》答案详解
介绍 昨天发的<大叔手记(19):你真懂JavaScript吗?>里面的5个题目,有很多回答,发现强人还是很多的,很多人都全部答对了. 今天我们来对这5个题目详细分析一下,希望对大家有所帮 ...
最新文章
- 当年学生的一件事,心情很难过
- Sklearn 损失函数如何应用到_Sklearn全复习(下)(持续更新)
- MATLAB语言算法实验报告,机械工程实验——matlab实验报告.doc
- 一行命令让ElasticSearch支持中文分词搜索
- c语言实现链表结构6,用c语言实现的链表结构--数据结构实验
- js提取正则中的字符串
- 深入理解Magento – 第六章 – 高级Magento模型
- IntelliJ IDEA 配置chrome插件调试js代码
- 广义表头尾链表存储结构_详解Redis五种数据结构的底层原理
- 云计算的思想领袖:与橡树岭国家实验室云计算研究员Rob Gillen的谈话
- 前端学习资料汇总(转)
- opencv 图像平滑处理(python)
- 香港虚拟主机租用价格
- Qt Creator 运行LVGL模拟器
- mac上如何测试html,Mac上实现Python用HTMLTestRunner生成html测试报告
- PointCloudLibrary点云库介绍
- 趣图:程序员先发现下雨了
- VMware-重要设置-虚拟网络编辑器
- Android自定义九宫格密码解锁
- 小白投资必备:主板、创业板、科创板、新三板区别与联系
热门文章
- c#过滤字符串中相同的字符串只保留一个
- 如何降低软件项目的风险 -- 包括客户的风险,软件提供商的风险
- Qt——菜单栏、工具栏、状态栏
- Python代码书写规范
- openstack安装newton版本dashboard+cinder(六)
- PHP之mb_convert_case使用
- hibernate映射(学生-科目-成绩)
- POJ 1486 Sorting Slides (二分图关键匹配边)
- 大数据框架对比:Hadoop、Storm、Samza、Spark和Flink
- 解决Eclipse出现的Failure to transfer ... jar问题