zoukankan      html  css  js  c++  java
  • Js杂谈-单体模式

    单体模式的思想:保证一个特定类仅有一个实例,意味着第二次使用同一个类创建新对象的时候,应该得到与第一次所创建对象完全相同的对象。

    下面举几个实现的例子

    1.new操作符

    这种思想在于当使用同一个构造函数以new操作符来创建多个对象,应该仅获得指向完全相同的对象的新指针。

    var uni = new Universe();
    var uni2 = new Universe();
    uni === uni2 //true

    2.静态属性中的实例

    function Universe(){
        if(typeof Universe.instance === 'object'){
            return Universe.instance;
        }
        this.a = '单体';
        Universe.instance = this;
    }
    
    var uni = new Universe();
    var uni2 = new Universe();
    uni === uni2 //true

    实例化的时候,先判断是否拥有实例,如果第一次实例化将跳过if判断,第二次实例化的时候,判断Universe的instance属性值是存在的,所以返回的是第一次实例化的结果。显然,这种方式的关键是使用全局变量来存储实例。当然使用全局变量的方式,弊端是非常明显的。

    3.闭包中的实例

    通过私有成员实现

    function Universe(){
        var instance = this;
        this.a = '单体';
        Universe = function(){
            return instance;
        };
    }
    
    var uni = new Universe();
    var uni2 = new Universe();
    uni === uni2 //true

    函数里返回函数,内部函数本身具有访问外部函数成员的权利,这是闭包的一次个人show。同样我们走一次测试代码。
    第一次实例化时,重写了Universe构造函数,返回的是this。从某种角度说,这种模式跟new很像,也有区别。相同都是new了Universe构造函数,不同在于实例化一次,就重写一次Universe构造函数。看到这里,这种实现方式的弊端也就显示出来了。看如下测试代码:

    Universe.prototype.nothing = true;
    var uni = new Universe();
    Universe.prototype.everything = true;
    var uni2 = new Universe();
    
    uni.nothing//true
    uni2.nothing//true
    
    uni.everything //undefined
    uni2.everything //undefined

    因为这种模式,每次实例化时,构造函数都被重写,所以此Universe.prototype非彼Universe.prototype。
    看看下面一种模式是如何解决的

    3.修改版

     function Universe(){
            //缓存实例
            var instance;
            //重写构造函数
            Universe = function(){
                return instance;
            };
            //保留原型属性
            Universe.prototype = this;
            //实例
            instance = new Universe();
            //重置构造函数指针
            instance.constructor = Universe;
            //所有功能
            instance.bang = 'big';
            return instance;
        }

    我们重新走一下之前版本的测试代码
    1.在Universe的原型上添加nothing属性。

    2.第一次实例化时,uni继承了Universe原型上的所有成员,之后重写构造函数,并将新的Universe的原型的指针置成uni。这样实例化之前的旧Universe原型上的成员就能转移到新的Universe的原型上了。

    3.在新的Universe的原型上添加everything属性

    4.第二次实例化时,过程跟2相同。

    这样。从开始的Universe的原型上的成员通过Universe.prototype = this,在每次实例化时转移给新的重写的Universe的原型上。

    4.另一种解决方案。(即时函数)

    var Universe;
    (function(){
        var instance;
        Universe = function Universe(){
            if(instance){
                return instance;
            }
            instance = this;
            this.a = '单体';
        }
    }())

    这种方案用了即时函数和闭包。在第一次调用构造函数时,它会创建一个对象。并且使得私有instance指向该对象。从第二次调用之后,该构造函数仅返回该私有变量。个人觉得。模式4和模式3是提供两种不错的解决思路。重写构造函数,通过闭包保存第一次初始化的对象。便于以后使用。
    东西不多,时间刚好。以上是本人学习感悟,有不对的地方请园友指正,大家共同学习进步。

    JavaScript是一座冰山,我所知道的只是冰山一角。

  • 相关阅读:
    李连杰开始做慈善事业了!
    世界是平的,这本书主要是写给美国人看的
    [问题征解]请解释下ubuntu 510 firefox的flash不发音的问题
    中医治疗慢性病很有效
    清理downloader病毒几百个,2个小时
    firefox2.0的拖放式搜索怎么不行了?是设置问题吗?
    spring live上有个入门的整合SSH的例子
    cctv的健康之路节目知识性和可看性都不错!
    跟你分享一下养生的经验
    cctv: 西医拒绝治疗的小孩,中医三天见效
  • 原文地址:https://www.cnblogs.com/wumadi/p/3145187.html
Copyright © 2011-2022 走看看