介绍

从本章开始,我们会逐步介绍在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); // true
console.log(uni2.bang); // 方法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); // true
console.log(uni2.nothing); // true
console.log(uni.everything); // true
console.log(uni2.everything); // true
console.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); // true
a.bang = "123";
alert(b.bang); // 参考资料 https://github.com/shichuan/javascript-patterns/blob/master/design-patterns/singleton.html http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript 同步与推荐 本文已同步至目录索引:深入理解JavaScript系列 深入理解JavaScript系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。

深入理解JavaScript系列(25):设计模式之单例模式的更多相关文章

  1. 深入理解JavaScript系列(38):设计模式之职责链模式

    介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象 ...

  2. 深入理解JavaScript系列(36):设计模式之中介者模式

    介绍 中介者模式(Mediator),用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 主要内容来自:http://www ...

  3. 深入理解JavaScript系列(30):设计模式之外观模式

    介绍 外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口值得这一子系统更加容易使用. 正文 外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦 ...

  4. 深入理解JavaScript系列(31):设计模式之代理模式

    介绍 代理,顾名思义就是帮助别人做事,GoF对代理模式的定义如下: 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 代理模式使得代理对象控制具体对象的引用.代理几乎可以是任何对 ...

  5. 深入理解JavaScript系列(33):设计模式之策略模式(转)

    介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很 ...

  6. 深入理解JavaScript系列(44):设计模式之桥接模式

    介绍 桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化. 正文 桥接模式最常用在事件监控上,先看一段代码: addEvent(element, 'click', getBe ...

  7. 深入理解JavaScript系列(42):设计模式之原型模式

    介绍 原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象. 正文 对于原型模式,我们可以利用JavaScript特有的原型继承特性去创建对象的方式,也就是 ...

  8. 深入理解JavaScript系列(43):设计模式之状态模式

    介绍 状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类. 正文 举个例子,就比如我们平时在下载东西,通常就会有好几个状态,比如准备状态(ReadySta ...

  9. 深入理解JavaScript系列(41):设计模式之模板方法

    介绍 模板方法(TemplateMethod)定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模板方法是一种代码复用的 ...

随机推荐

  1. 「Luogu 1471」 方差

    题目背景 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差. 输入输出 ...

  2. C# LINQ(7)

    大部分的LINQ的关键字都说了,最后说一下排序吧. LINQ的是查询的利器. 那么查询就会有排序. 所有LINQ提供了两种简单的排序.倒序和默认排序. 关键字是: orderby ascending ...

  3. spring (1)

    相关名词: 控制反转(IoC):将对象的创建交由spring创建,1创建新class,2xml中配置 3测试context.getBean("") 类似对象工厂(工厂模式)-xml ...

  4. NSLocale 本地化信息

    前言 NSLocale 类返回本地化信息,主要体现在"语言"和"区域格式"这两个设置项. 1.NSLocale 本地化信息的创建 // 用标示符创建 NSLoc ...

  5. 新增扩展程序功能打包提交新版 WARNING ITMS-90473 警告问题

    1.问题描述 自从在主应用中加入SiriShortCut功能之后,打包程序上传至 iTunes Connect 就会出现警告,看其原因描述是CFBundleVersion主应用与子应用的不一致导致的 ...

  6. react.js学习之路五

    最近没时间写博客,但是我一直在学习react,我发现react是一个巨大的坑,而且永远填不完的坑 关于字符串的拼接: 在react中,字符串的拼接不允许出现双引号“” ,只能使用单引号' ',例如这样 ...

  7. 用python写个快排

    快排过程比较简单就直接上代码了: #!/usr/bin/python3 def quik_sort(L, left, right): if left <= right: key = L[left ...

  8. 题解 P1534 【不高兴的津津(升级版)】

    题目链接 不算太难.就是题目有歧义. wa了好几次才发现.上一天要是小于8的话.结算是昨天一个负值在加上今天课时数.再减去8.233.... 而不是上一天小于8个小时.就清零了..大家要注意(ps:题 ...

  9. [HEOI2012]采花 树状数组 BZOJ 2743

    题目描述 萧薰儿是古国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花. 花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一排的,以便于 ...

  10. ajax beforeSend中无效果

    asnyc:false 与beforesend 同时使用 无效果