JS设计模式---5.单体模式
2018-12-12 本文已影响65人
念丶凉
何为单体模式
单体是一个用来划分命名空间并将相关一批方法和属性组织在一起的对象,如果它可以被实例化,那么它只能被实例化一次。
单体模式之利
- 调试维护轻松,利于理解
- 防止误改,提升网页稳定性
- 减少不必要的内存消耗(宽带消耗)
单体模式之弊
- 会导致模块间的强耦合
- 不利于单元测试
认识单体及其应用
单体的基本结构
var Singleton = {
attribute1:true,
attribute2:10,
method1:function(){
},
method2:function () {
}
}
其实就是字面量对象,如果按照严格的定义来说,这并不能算一个单体,因为它不是一个可以实例化的类。
划分命名空间
单体对象由两个部分组成:包含着方法和属性成员的对象本身,以及用于访问它的变量。
function findProduct() {
console.log('555')
}
findProduct(); // 555
var findProduct = function () {
console.log('666')
}
findProduct() //666
函数中声明变量时如果不使用var关键字,那么变量将被声明为全局性的。因此会干扰到全局命名空间中的其他代码
var MyNamespace = {
findProduct:function(){
// ...
}
}
// 现在findProduct函数是MyNamespace中的一个方法,它不会被全局命名中声明的任何新变量改写
// 命名空间还可以进异步分割,如下
var GiantCorp = {};
GiantCorp.Common = {
// ...
}
GiantCorp.ErrorCodes = {
// ...
}
GiantCorp.PageHandler = {
// ...
}
用做特定网页专用代码的单体
已经了解到如何把单体作为命名空间使用后,我们还需要知道单体模式的一个特殊用途。在拥有许多网页的网站中,有些js代码是所有网页都要用到的,他们通常被放在独立的文件中。比如我们经常用到的jquery, lodash.js等他们就是作专用代码的单体
拥有私用成员的单体
下划线表示法
// 默认GianCorp存在
GianCorp.DataParser = {
// 私有方法
_srtipWhitespace:function(str){
return str.replace(/\s+/,'');
},
_stringSplit:function (str,delimiter) {
return str.split(delimiter)
},
// 公用方法
srtingToArray:function(str,delimiter,stripWs){
if (stripWs) {
str= this._srtipWhitespace(str)
}
var outputArray = this._stringSplit(str,delimiter)
return outputArray
}
}
这个栗子中的单体对象有一个公用方法srtingToArray:function,它的主要工作靠_srtipWhitespace和_stringSplit这两个私有方法完成。将他们设计为私有方法,重构所有内部代码时就不必担心会殃及别人的程序。下划线这个标记前面也讲过,一般情况下是没有人调用它的。
闭包
MyNamespace.singleton= (function () {
// 私有成员
var privateAttribute1 = false;
var privateAttribute2 = [1,2,3];
function privateMethod1() {
//...
};
function privateMethod2() {
//...
};
return {
//公共成员
publicAttribute1:true,
publicAttribute2:10,
publicMethod1:function(){
//...
},
publicMethod2:function(){
//...
}
}
})()
这种单体模式又称模块模式,指的是它可以吧一批相关方法和属性组织为模块并起到划分命名空间的作用。
这种模式与下划线表示法相比有亟待呢优势。把私有成员放到闭包中可以确保其不会在单体对象之外被使用。你可以自由地改变对象的实现细节,还不会殃及比尔的代码。还可以用这种方法对数据进行保护和封装。
惰性实例化
前面所讲的单体模式的各种实现方式有一个共同点:单体对象都是在脚本加载时被创建出来。对于资源密集型的或配置开销甚大的单体,更合理的做法是将其实例化推迟到需要使用它的时候。这种技术被称为惰性加载。
MyNamespace.singleton= (function () {
var uniqueInstance; //实例
function constructor() { //构造器 (最终返回的单体)
// 私有成员
var privateAttribute1 = false;
var privateAttribute2 = [1,2,3];
function privateMethod1() {
//...
};
function privateMethod2() {
//...
};
return {
//公共成员
publicAttribute1:true,
publicAttribute2:10,
publicMethod1:function(){
//...
},
publicMethod2:function(){
//...
}
}
};
return {
getInstance:function(){
if (!uniqueInstance) { // 判断实例存不存在
uniqueInstance = constructor()
}
return uniqueInstance;
}
}
})()
// 使用
// MyNamespace.singleton.publicMethod1() before
MyNamespace.singleton.getInstance().publicMethod1() //after
分支
MyNamespace.singleton= (function () {
var obj1 = {
//...
}
var obj2 = {
// ...
}
return (someCondition)?obj1:obj2
})()
主要做兼容用