JS设计模式 - 单例模式

《JavaScript设计模式》单例模式学习小结

一、解释

单例模式,又称单体(singleton)模式。单体是一个对象。具体来说是,用来划分命名空间,并将一批方法和属性组织起来对象。它使代码成为一个逻辑单元,确保所有代码使用的都是同样的全局资源。

单体的基本结构如下:

var Singleton = {
    username: '',
    login: function () {

    }
}

二、单体的使用

1. 用于划分命名空间的单体

单体对象内所有成员都被包装在这个对象中,所以它们不是全局的;由于这些成员只能通过单体对象变量进行访问,可以说它们统一存在于这一个命名空间内。

2. 在单体对象中创建私用成员

1)下划线表示私用成员

🌰举例:

myNamespace.Singleton = {
    // 私有方法
    _stripWhitespace: function (str) {
        return str.replace(whitespaceRegex, '');
    },
    _stringSplit: function (str, delimiter) {
        return str.split(delimiter);
    },
    // 公共方法
    stringToArray: function (str, delimiter, stripWS) {
        if (stripWS) {
            str = stripWhitespace(str);
        }
        var outputArray = stringSplit(str, delimiter);
        return outputArray;
    }
}

2)使用闭包

🌰举例:

myNamespace.Singleton = (function () {
    // 私有属性
    var whitespaceRegex = /\s+/;
    // 私有方法
    function stripWhitespace(str) {
        return str.replace(whitespaceRegex, '');
    }
    function stringSplit(str, delimiter) {
        return str.split(delimiter);
    }
    return {
        // 公共方法
        stringToArray: function (str, delimiter, stripWS) {
            if (stripWS) {
                str = stripWhitespace(str);
            }
            var outputArray = stringSplit(str, delimiter);
            return outputArray;
        }
    }
})();

注意:下面两个写法创建的 myNamespace.Singleton 是一样的。匿名函数返回了一个对象。

myNamespace.Singleton = (function(){
    return{
    }
})();

myNamespace.Singleton = {}

3. 单体的惰性实例化

前面的单体模式的实现方式是立刻创建,但对开销大的单体,更合理的是在需要的时候加载,即惰性加载。惰性加载单体的访问需要借助静态方法:Singleton.getInstance.methodName 。getInstance 会检查单体是否被实例化,如果没有会创建并返回实例,否则直接返回现有实例。

🌰举例:把原来单体中的代码移到 constructor 方法中,这个方法不能从闭包外部访问。于是我们可以通过写一个公共方法 getInstance 来实现其调用时机的控制。

myNamespace.Singleton = (function(){
Var uniqueInstance;
Function constructor(){
	// 私有属性
    var whitespaceRegex = /\s+/;
    // 私有方法
    function stripWhitespace(str){
        return str.replace(whitespaceRegex, '');
    }
    function stringSplit(str, delimiter){
        return str.split(delimiter);
    }
    return{
        // 公用方法
        stringToArray: function(str, delimiter, stripWS){
            if(stripWS){
              str = stripWhitespace(str);
            }
            var outputArray = stringSplit(str, delimiter);
            return outputArray;
        }
    }
}
return{
   getInstance: function(){
      If(!uniqueInstance){
	   uniqueInstance = constructor();
}
      Return uniqueInstance;
}
    }
})();

myNamespace.Singleton.getInstance().stringToArray()

注意:被用于命名空间、或组织相关使用方法的工具的单体最好还是立即实例化。

4. 分支技术

前面的模式中,单体对象的所有代码都是在运行时确定的,也可以使用应变代码,这就用到了分支技术。

🌰举例:用分支技术创建XHR对象。用了分支技术后,嗅探代码只执行一次,而非每生成一个对象执行一次。

var SimpleXhrFactory = (function () {
    var standard = {
        createXhrObject: function () {
            return new XMLHttpRequest();
        }
    };
    var activeXNew = {
        createXhrObject: function () {
            return new ActiveXObject('Msxml2');
        }
    };
    var activeXOld = {
        createXhrObject: function () {
            return new ActiveXObject('Microsoft');
        }
    };
    var testObject;
    try {
        testObject = standard.createXhrObject();
        return standard;
    } catch (e) {
        try {
            testObject = activeXNew.createXhrObject();
            return activeXNew;
        } catch (e) {
            try {
                testObject = activeXOld.createXhrObject();
                return activeXOld;
            } catch (e) {
                throw new Error('no xhr object found')
            }
        }
    }
})();

注意:使用的时候需要在计算的时间和占用的内存空间中做权衡。

三、单体模式的优缺点

1. 优点

 - 把私有成员放在闭包中,确保不会在单体对象之外被使用;

 - 可以自由改变对象的实现方式,对数据进行保护和封装且不会影响到别人的代码、第三方库代码;

 - 避免重复引用逻辑混乱、性能消耗;

 - 使用惰性实例化技术,直到需要对象的时候再创建,可以减少不必要的内存消耗;

 - 使用分支技术,根据运行条件创建方法,且不会在每次调用都浪费时间去检查运行环境。

2. 缺点

 - 可能导致模块间的强耦合,不利于单元测试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值