一:单体的基本结构

最简单的单体,实际就是一个对象字面量:
var Singleton = {
attribute1: true,
attribute2: , method1: function() { },
method2: function(arg) { }
};
二:划分命名空间
单体一个很重要的功能就是划分命名空间,这节其实没什么好说的。。
然后,最好的做法是将命名空间再进一步统一,使自己的所有代码都通过一个全局对象来访问,例子:
var GiantCorp = {};

GiantCorp.Common = {
// A singleton with common methods used by all objects and modules.
}; GiantCorp.ErrorCodes = {
// An object literal used to store data.
}; GiantCorp.PageHandler = {
// A singleton with page specific methods and attributes.
};
然后这样的话,与外部的代码发生冲突的可能性就超级少了
三:用作特定网页专用代码的包装器的单体
单体的另一个重要的功能就是包装网页专用代码:
Namespace.PageName = {

  // Page constants.
CONSTANT_1: true,
CONSTANT_2: , // Page methods.
method1: function() { },
method2: function() { }, // Initialization method.
init: function() { }
}
然后就调用这些代码
addLoadEvent(Namespace.PageName.init);
接下来举一个实际使用的例子:我们现在写网页基本上必写的就是用ajax提交表单,那么我们怎样用单体来包装这些代码呢?下面就是一个演示:
先来反例(我自己之前的做法~~~):
var formID = document.getElementById("form");
formID.addEventListener('submit',formSubmit,false); function formSubmit(e) {
//阻止表单默认动作,然后用ajax发送数据
//接受数据之后调用callBack函数
} function callBack(data) {
//用ajax提交表单之后的回调函数
这样的话污染了超级多的全局变量~~~
然后学习这章之后的做法~~~
var GiantCorp = window.GiantCorp || {};
GiantCorp.RegPage = {
formID: 'form',
callBack: function(data) {
//用ajax提交表单之后的回调函数
},
formSubmit: function(e) {
//阻止表单默认动作,然后用ajax发送数据
//接受数据之后调用callBack函数
},
init: function(e) {
GiantCorp.RegPage.formEl = document.getElementById(GiantCorp.RegPage.formID);
GiantCorp.RegPage.formEl.addEventListener('submit',GiantCorp.RegPage.formSubmit,false);
}
} GiantCorp.RegPage.init();
注意第一行代码,意思就是如果之前定义过GiantCorp的话就不管,不然就赋予一个空对象给GiantCorp,这样的代码在很多地方都会看到。
四:拥有私用成员的单体
拥有私用成员的最简单方法就是在属性前加下划线_来区分:
GiantCorp.DataParser = {
// Private methods.
_stripWhitespace: function(str) {
return str.replace(/\s+/, '');
},
_stringSplit: function(str, delimiter) {
return str.split(delimiter);
}, // Public method.
stringToArray: function(str, delimiter, stripWS) {
if(stripWS) {
str = this._stripWhitespace(str);
}
var outputArray = this._stringSplit(str, delimiter);
return outputArray;
}
};
上面的代码不用去理解它,看到下划线_就把它当成是私有属性就可以了
此外stringToArray的函数里面用了this来直接调用单体里面的其他方法,不过使用起来注意它有时候指向的对象的问题!
接下来是使用闭包来实现真正拥有私用成员的单体:
MyNamespace.Singleton = (function() {
// Private members.
var privateAttribute1 = false;
var privateAttribute2 = [, , ]; function privateMethod1() {
...
}
function privateMethod2(args) {
...
} return { // Public members.
publicAttribute1: true,
publicAttribute2: , publicMethod1: function() {
...
},
publicMethod2: function(args) {
...
}
};
})();
注意是公共成员都是放在return里面的,其他都是私有的。
这种模式是JavaScript中最流行,应用最广泛的模式之一
五:惰性实例化
又来一个比较高级的做法,那就是惰性实例化:当我们需要用到这段代码的时候才创建它。换种方法说就是这样调用其方法:Singleton.getInstance().methodName(),而不是这样调用:Singleton.methodName()。其中getInstance方法会检查该单体是否已经被实例化。如果还没有,那么它将创建并返回其实例,如果单体已经实例过,那么它将返回现有实例。
 
实现步骤一(单体的所有代码移动一个名为constructor的方法中):
MyNamespace.Singleton = (function() {

  function constructor() { // All of the normal singleton code goes here.
// Private members.
var privateAttribute1 = false;
var privateAttribute2 = [, , ]; function privateMethod1() {
...
}
function privateMethod2(args) {
...
} return { // Public members.
publicAttribute1: true,
publicAttribute2: , publicMethod1: function() {
...
},
publicMethod2: function(args) {
...
}
}
} })();
上面注意constructor是包含单体里面所有代码的。
实现步骤二(创建一个单体控制的函数,并返回到单体):
MyNamespace.Singleton = (function() {

  function constructor() { // All of the normal singleton code goes here.
...
} return {
getInstance: function() {
// Control code goes here.
}
}
})();
实现步骤三(创建个私有变量用于判断是否已经实例化,并且在getInstance实现判断逻辑):
MyNamespace.Singleton = (function() {

  var uniqueInstance; // Private attribute that holds the single instance.

  function constructor() { // All of the normal singleton code goes here.
...
} return {
getInstance: function() {
if(!uniqueInstance) { // Instantiate only if the instance doesn't exist.
uniqueInstance = constructor();
}
return uniqueInstance;
}
}
})();
此外,可以用 var MNS = MyNamespace.Singleton的方法简化命名空间,但是要注意this指向问题!
六:分支
利用分支可以实现判断浏览器支持哪一种代码,然后对该浏览器使用专用的代码:
MyNamespace.Singleton = (function() {
var objectA = {
method1: function() {
...
},
method2: function() {
...
}
};
var objectB = {
method1: function() {
...
},
method2: function() {
...
}
}; return (someCondition) ? objectA : objectB;
})();
用上面这样的分支我们就可以用来实现如果是IE8就返回第一种单体,如果不是就返回第二种单体了。
七:示例:用分支技术创建XHR对象
如果要兼容老旧的浏览器使用ajax,那就可以用这种技术了
例子:
/* SimpleXhrFactory singleton, step 1. */

var SimpleXhrFactory = (function() {

  // The three branches.
var standard = {
createXhrObject: function() {
return new XMLHttpRequest();
}
};
var activeXNew = {
createXhrObject: function() {
return new ActiveXObject('Msxml2.XMLHTTP');
}
};
var activeXOld = {
createXhrObject: function() {
return new ActiveXObject('Microsoft.XMLHTTP');
}
}; })(); /* SimpleXhrFactory singleton, step 2. */ var SimpleXhrFactory = (function() { // The three branches.
var standard = {
createXhrObject: function() {
return new XMLHttpRequest();
}
};
var activeXNew = {
createXhrObject: function() {
return new ActiveXObject('Msxml2.XMLHTTP');
}
};
var activeXOld = {
createXhrObject: function() {
return new ActiveXObject('Microsoft.XMLHTTP');
}
}; // To assign the branch, try each method; return whatever doesn't fail.
var testObject;
try {
testObject = standard.createXhrObject();
return standard; // Return this if no error was thrown.
}
catch(e) {
try {
testObject = activeXNew.createXhrObject();
return activeXNew; // Return this if no error was thrown.
}
catch(e) {
try {
testObject = activeXOld.createXhrObject();
return activeXOld; // Return this if no error was thrown.
}
catch(e) {
throw new Error('No XHR object found in this environment.');
}
}
} })();

《javascript设计模式》笔记之第五章:单体模式的更多相关文章

  1. javascript设计模式学习之十五——装饰者模式

    一.装饰者模式定义 装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.这种为对象动态添加职责的方式就称为装饰者模式.装饰者对象和它所装饰的对象拥有一致的接口,对于用 ...

  2. [书籍翻译] 《JavaScript并发编程》第五章 使用Web Workers

    本文是我翻译<JavaScript Concurrency>书籍的第五章 使用Web Workers,该书主要以Promises.Generator.Web workers等技术来讲解Ja ...

  3. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...

  4. Java 设计模式系列(十五)迭代器模式(Iterator)

    Java 设计模式系列(十五)迭代器模式(Iterator) 迭代器模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象(interna ...

  5. Javascript设计模式理论与实战:工厂方法模式

    本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用.在之前的<Javascript设计模式理论与实战:简单工厂模 ...

  6. JavaScript DOM编程艺术-学习笔记(第五章、第六章)

    第五章: 1.题外话:首先大声疾呼,"js无罪",有罪的是滥用js的那些人.js的father 布兰登-艾克,当初为了应付工作,10天就赶出了这个js,事后还说人家js是c语言和s ...

  7. Javascript设计模式笔记

    Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...

  8. 《LINUX内核设计与实现》读书笔记之第五章

    第五章——系统调用 5.1 与内核通信 1.为用户空间提供一种硬件的抽象接口 2.保证系统稳定和安全 3.除异常和陷入,是内核唯一的合法入口. API.POSIX和C库 关于Unix接口设计:提供机制 ...

  9. Linux内核分析 读书笔记 (第五章)

    第五章 系统调用 5.1 与内核通信 1.调用在用户空间进程和硬件设备之间添加了一个中间层.该层主要作用有三个: 为用户空间提供了硬件的抽象接口. 系统调用保证了系统的稳定和安全. 实现多任务和虚拟内 ...

随机推荐

  1. tomcat启动项目被重新加载,导致资源初始化两遍

    之前没有遇到过这个问题,配了三天的项目了,惊人啊!!!各种怪问题全被我赶上了.真有种骂人的冲动. tomcat启动项目时,项目资源被加载两遍. 原因:配置虚拟目录导致,项目被重新加载. <Hos ...

  2. docker中Ubuntu安装jdk1.8

    1.在宿主系统下载所需要的jdk版本的gz文件 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133 ...

  3. template <typename T>模板类定义

    #include "stdafx.h"#include "iostream"#include <ctime>using namespace std; ...

  4. ubuntu 下编译安装ceph

    git clone --recursive https://github.com/ceph/ceph.git  cd ceph/  sudo apt-get install libtool   sud ...

  5. ADB命令小结

    )adb devices //查看启动的所有设备 )adb kill-server //重启设备 )adb start-server //启动设备 )adb -s emulator-(通过 adb d ...

  6. 如何正确遍历删除List中的元素,你会吗?

    遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过增强的for循环删除符合条件的多个元素 2.通过增强的for循环删除符合 ...

  7. 一、使用 BeautifulSoup抓取网页信息信息

    一.解析网页信息 from bs4 import BeautifulSoup with open('C:/Users/michael/Desktop/Plan-for-combating-master ...

  8. 【Hadoop】HDFS笔记(三):HDFS的Shell操作

    HDFS处理文件的命令和Linux命令差不多,但注意区分大小写. (Linux区分大小写,Windows不区分大小写) 一.fs命令 键入命令"./bin/hadoop fs"将输 ...

  9. sqlserver——视图

    数据库中的视图是一个虚拟表.同真实的表一样,视图包含一系列带有名称的列和行数据,行和列数据用来自由定义视图和查询所引用的表,并且在引用视图时动态产生.本篇将通过一些实例来介绍视图的概念,视图的作用,创 ...

  10. E20180518-hm

    priority  n. 优先,优先权; (时间,序上的) 先,前; 优先考虑的事; [数] 优先次序;